ARM: Merge for-2635/fb-updates1

Merge branch 'for-2635/fb-updates1' into for-linus/samsung2
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1594739..9505a70 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -110,6 +110,8 @@
 head-y		:= arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
 textofs-y	:= 0x00008000
 textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000
+# We don't want the htc bootloader to corrupt kernel during resume
+textofs-$(CONFIG_PM_H1940)      := 0x00108000
 # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
 ifeq ($(CONFIG_ARCH_SA1100),y)
 textofs-$(CONFIG_SA1111) := 0x00208000
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 9e5e96f..a4c0b3f 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -96,12 +96,19 @@
 config MACH_N30
 	bool "Acer N30 family"
 	select CPU_S3C2410
+	select MACH_N35
 	select S3C_DEV_USB_HOST
 	select S3C_DEV_NAND
 	help
 	  Say Y here if you want suppt for the Acer N30, Acer N35,
 	  Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
 
+config MACH_N35
+	bool
+	help
+	  Internal node in order to enable support for Acer N35 if Acer N30 is
+	  selected.
+
 config ARCH_BAST
 	bool "Simtec Electronics BAST (EB2410ITX)"
 	select CPU_S3C2410
@@ -111,6 +118,7 @@
 	select MACH_BAST_IDE
 	select S3C24XX_DCLK
 	select ISA
+	select S3C_DEV_HWMON
 	select S3C_DEV_USB_HOST
 	select S3C_DEV_NAND
 	help
diff --git a/arch/arm/mach-s3c2410/Makefile.boot b/arch/arm/mach-s3c2410/Makefile.boot
index 7dab2a0..58c1dd7 100644
--- a/arch/arm/mach-s3c2410/Makefile.boot
+++ b/arch/arm/mach-s3c2410/Makefile.boot
@@ -1,3 +1,7 @@
-   zreladdr-y	:= 0x30008000
-params_phys-y	:= 0x30000100
-
+ifeq ($(CONFIG_PM_H1940),y)
+	zreladdr-y		:= 0x30108000
+	params_phys-y	:= 0x30100100
+else
+	zreladdr-y		:= 0x30008000
+	params_phys-y	:= 0x30000100
+endif
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
index f3182ff..4f7bf32 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
@@ -16,15 +16,28 @@
 
 #define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
 
-#define S3C2410_GPIO_BANKA   (32*0)
-#define S3C2410_GPIO_BANKB   (32*1)
-#define S3C2410_GPIO_BANKC   (32*2)
-#define S3C2410_GPIO_BANKD   (32*3)
-#define S3C2410_GPIO_BANKE   (32*4)
-#define S3C2410_GPIO_BANKF   (32*5)
 #define S3C2410_GPIO_BANKG   (32*6)
 #define S3C2410_GPIO_BANKH   (32*7)
 
+/* GPIO sizes for various SoCs:
+ *
+ *             2442
+ *   2410 2412 2440 2443 2416
+ *   ---- ---- ---- ---- ----
+ * A 23   22   25   16   25
+ * B 11   11   11   11   9
+ * C 16   15   16   16   16
+ * D 16   16   16   16   16
+ * E 16   16   16   16   16
+ * F 8    8    8    8    8
+ * G 16   16   16   16   8
+ * H 11   11   9    15   15
+ * J --   --   13   16   --
+ * K --   --   --   --   16
+ * L --   --   --   15   7
+ * M --   --   --   2    2
+ */
+
 /* GPIO bank sizes */
 #define S3C2410_GPIO_A_NR	(32)
 #define S3C2410_GPIO_B_NR	(32)
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-track.h b/arch/arm/mach-s3c2410/include/mach/gpio-track.h
index acb2591..d67819d 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio-track.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio-track.h
@@ -23,11 +23,11 @@
 {
 	struct s3c_gpio_chip *chip;
 
-	if (pin > S3C2410_GPG(10))
+	if (pin > S3C_GPIO_END)
 		return NULL;
 
 	chip = &s3c24xx_gpios[pin/32];
-	return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL;
+	return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL;
 }
 
 #endif /* __ASM_ARCH_GPIO_CORE_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h
index 15f0b3e..b649bf2 100644
--- a/arch/arm/mach-s3c2410/include/mach/gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/gpio.h
@@ -20,10 +20,18 @@
  * devices that need GPIO.
  */
 
+#ifdef CONFIG_CPU_S3C244X
+#define ARCH_NR_GPIOS	(32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA)
+#else
 #define ARCH_NR_GPIOS	(256 + CONFIG_S3C24XX_GPIO_EXTRA)
+#endif
 
 #include <asm-generic/gpio.h>
 #include <mach/gpio-nrs.h>
 #include <mach/gpio-fns.h>
 
+#ifdef CONFIG_CPU_S3C24XX
+#define S3C_GPIO_END	(S3C2410_GPIO_BANKJ + 32)
+#else
 #define S3C_GPIO_END	(S3C2410_GPIO_BANKH + 32)
+#endif
diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
index a638423..a0a89d4 100644
--- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
+++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
@@ -17,29 +17,11 @@
 #include <mach/gpio-nrs.h>
 
 #ifdef CONFIG_CPU_S3C2400
-#define S3C24XX_GPIO_BASE(x)  S3C2400_GPIO_BASE(x)
-#define S3C24XX_MISCCR        S3C2400_MISCCR
+#define S3C24XX_MISCCR		S3C2400_MISCCR
 #else
-#define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)
-#define S3C24XX_MISCCR	      S3C24XX_GPIOREG2(0x80)
+#define S3C24XX_MISCCR		S3C24XX_GPIOREG2(0x80)
 #endif /* CONFIG_CPU_S3C2400 */
 
-
-/* S3C2400 doesn't have a 1:1 mapping to S3C2410 gpio base pins */
-
-#define S3C2400_BANKNUM(pin)     (((pin) & ~31) / 32)
-#define S3C2400_BASEA2B(pin)     ((((pin) & ~31) >> 2))
-#define S3C2400_BASEC2H(pin)     ((S3C2400_BANKNUM(pin) * 10) + \
-                                 (2 * (S3C2400_BANKNUM(pin)-2)))
-
-#define S3C2400_GPIO_BASE(pin)   (pin < S3C2410_GPIO_BANKC ? \
-                                 S3C2400_BASEA2B(pin)+S3C24XX_VA_GPIO : \
-                                 S3C2400_BASEC2H(pin)+S3C24XX_VA_GPIO)
-
-
-#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
-#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
-
 /* general configuration options */
 
 #define S3C2410_GPIO_LEAVE   (0xFFFFFFFF)
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index b061ddc..c1f90f6 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -633,7 +633,7 @@
 
 	s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
 
-	s3c_device_hwmon.dev.platform_data = &bast_hwmon_info;
+	s3c_hwmon_set_platdata(&bast_hwmon_info);
 
 	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
 	s3c24xx_init_clocks(0);
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 9531b4c..d2a2fad 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -163,8 +163,8 @@
 	.xres =		240,
 	.yres =		320,
 	.bpp =		16,
-	.left_margin =	20,
-	.right_margin =	8,
+	.left_margin =	8,
+	.right_margin =	20,
 	.hsync_len =	4,
 	.upper_margin =	8,
 	.lower_margin = 7,
@@ -272,7 +272,6 @@
 };
 
 static struct platform_device *h1940_devices[] __initdata = {
-	&s3c_device_ts,
 	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
@@ -286,6 +285,8 @@
 	&s3c_device_timer[0],
 	&h1940_backlight,
 	&h1940_lcd_powerdev,
+	&s3c_device_adc,
+	&s3c_device_ts,
 };
 
 static void __init h1940_map_io(void)
@@ -339,7 +340,7 @@
 }
 
 MACHINE_START(H1940, "IPAQ-H1940")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 75a9fd3..41f299d 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -26,6 +26,7 @@
 #include <linux/serial_core.h>
 #include <linux/timer.h>
 #include <linux/io.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
@@ -46,6 +47,7 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/mci.h>
 #include <plat/s3c2410.h>
 #include <plat/udc.h>
 
@@ -172,8 +174,10 @@
 	{
 		.gpio		= S3C2410_GPF(0),
 		.code		= KEY_POWER,
+		.type		= EV_PWR,
 		.desc		= "Power",
 		.active_low	= 0,
+		.wakeup		= 1,
 	},
 	{
 		.gpio		= S3C2410_GPG(9),
@@ -264,6 +268,14 @@
 	.def_trigger	= "",
 };
 
+/* This is the blue LED on the device. Originaly used to indicate GPS activity
+ * by flashing. */
+static struct s3c24xx_led_platdata n35_blue_led_pdata = {
+	.name		= "blue_led",
+	.gpio		= S3C2410_GPD(8),
+	.def_trigger	= "",
+};
+
 /* This LED is driven by the battery microcontroller, and is blinking
  * red, blinking green or solid green when the battery is low,
  * charging or full respectively.  By driving GPD9 low, it's possible
@@ -275,6 +287,13 @@
 	.def_trigger	= "",
 };
 
+static struct s3c24xx_led_platdata n35_warning_led_pdata = {
+	.name		= "warning_led",
+	.flags          = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.gpio		= S3C2410_GPD(9),
+	.def_trigger	= "",
+};
+
 static struct platform_device n30_blue_led = {
 	.name		= "s3c24xx_led",
 	.id		= 1,
@@ -283,6 +302,14 @@
 	},
 };
 
+static struct platform_device n35_blue_led = {
+	.name		= "s3c24xx_led",
+	.id		= 1,
+	.dev		= {
+		.platform_data	= &n35_blue_led_pdata,
+	},
+};
+
 static struct platform_device n30_warning_led = {
 	.name		= "s3c24xx_led",
 	.id		= 2,
@@ -291,6 +318,14 @@
 	},
 };
 
+static struct platform_device n35_warning_led = {
+	.name		= "s3c24xx_led",
+	.id		= 2,
+	.dev		= {
+		.platform_data	= &n35_warning_led_pdata,
+	},
+};
+
 static struct s3c2410fb_display n30_display __initdata = {
 	.type		= S3C2410_LCDCON1_TFT,
 	.width		= 240,
@@ -317,13 +352,36 @@
 	.lpcsel		= 0x06,
 };
 
+static void n30_sdi_set_power(unsigned char power_mode, unsigned short vdd)
+{
+	switch (power_mode) {
+	case MMC_POWER_ON:
+	case MMC_POWER_UP:
+		gpio_set_value(S3C2410_GPG(4), 1);
+		break;
+	case MMC_POWER_OFF:
+	default:
+		gpio_set_value(S3C2410_GPG(4), 0);
+		break;
+	}
+}
+
+static struct s3c24xx_mci_pdata n30_mci_cfg __initdata = {
+	.gpio_detect	= S3C2410_GPF(1),
+	.gpio_wprotect  = S3C2410_GPG(10),
+	.ocr_avail	= MMC_VDD_32_33,
+	.set_power	= n30_sdi_set_power,
+};
+
 static struct platform_device *n30_devices[] __initdata = {
 	&s3c_device_lcd,
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
 	&s3c_device_ohci,
+	&s3c_device_rtc,
 	&s3c_device_usbgadget,
+	&s3c_device_sdi,
 	&n30_button_device,
 	&n30_blue_led,
 	&n30_warning_led,
@@ -334,8 +392,12 @@
 	&s3c_device_wdt,
 	&s3c_device_i2c0,
 	&s3c_device_iis,
+	&s3c_device_rtc,
 	&s3c_device_usbgadget,
+	&s3c_device_sdi,
 	&n35_button_device,
+	&n35_blue_led,
+	&n35_warning_led,
 };
 
 static struct s3c2410_platform_i2c __initdata n30_i2ccfg = {
@@ -490,17 +552,15 @@
 	s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
 }
 
-static void __init n30_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
-
 /* GPB3 is the line that controls the pull-up for the USB D+ line */
 
 static void __init n30_init(void)
 {
+	WARN_ON(gpio_request(S3C2410_GPG(4), "mmc power"));
+
 	s3c24xx_fb_set_platdata(&n30_fb_info);
 	s3c24xx_udc_set_platdata(&n30_udc_cfg);
+	s3c24xx_mci_set_platdata(&n30_mci_cfg);
 	s3c_i2c0_set_platdata(&n30_i2ccfg);
 
 	/* Turn off suspend on both USB ports, and switch the
@@ -532,7 +592,7 @@
 		s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
 				      S3C2410_MISCCR_USBSUSPND0 |
 				      S3C2410_MISCCR_USBSUSPND1,
-				      S3C2410_MISCCR_USBSUSPND1);
+				      S3C2410_MISCCR_USBSUSPND0);
 
 		platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices));
 	}
@@ -550,7 +610,7 @@
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
-	.init_irq	= n30_init_irq,
+	.init_irq	= s3c24xx_init_irq,
 	.map_io		= n30_map_io,
 MACHINE_END
 
@@ -562,6 +622,6 @@
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
 	.timer		= &s3c24xx_timer,
 	.init_machine	= n30_init,
-	.init_irq	= n30_init_irq,
+	.init_irq	= s3c24xx_init_irq,
 	.map_io		= n30_map_io,
 MACHINE_END
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index 966119c..725636f 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -60,10 +60,10 @@
 		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
 	}
 
-	/* the RX3715 uses similar code and the same H1940 and the
+	/* RX3715 and RX1950 use similar to H1940 code and the
 	 * same offsets for resume and checksum pointers */
 
-	if (machine_is_rx3715()) {
+	if (machine_is_rx3715() || machine_is_rx1950()) {
 		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
 		unsigned long ptr;
 		unsigned long calc = 0;
@@ -79,6 +79,17 @@
 	if ( machine_is_aml_m5900() )
 		s3c2410_gpio_setpin(S3C2410_GPF(2), 1);
 
+	if (machine_is_rx1950()) {
+		/* According to S3C2442 user's manual, page 7-17,
+		 * when the system is operating in NAND boot mode,
+		 * the hardware pin configuration - EINT[23:21] –
+		 * must be set as input for starting up after
+		 * wakeup from sleep mode
+		 */
+		s3c_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPIO_INPUT);
+	}
 }
 
 static int s3c2410_pm_resume(struct sys_device *dev)
diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c
index f7afece..3404a87 100644
--- a/arch/arm/mach-s3c2412/gpio.c
+++ b/arch/arm/mach-s3c2412/gpio.c
@@ -16,41 +16,43 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include <mach/regs-gpio.h>
-
 #include <mach/hardware.h>
 
+#include <plat/gpio-core.h>
+
 int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	unsigned long offs = pin - chip->chip.base;
 	unsigned long flags;
 	unsigned long slpcon;
 
 	offs *= 2;
 
-	if (pin < S3C2410_GPIO_BANKB)
+	if (pin < S3C2410_GPB(0))
 		return -EINVAL;
 
-	if (pin >= S3C2410_GPIO_BANKF &&
-	    pin <= S3C2410_GPIO_BANKG)
+	if (pin >= S3C2410_GPF(0) &&
+	    pin <= S3C2410_GPG(16))
 		return -EINVAL;
 
-	if (pin > (S3C2410_GPIO_BANKH + 32))
+	if (pin > S3C2410_GPH(16))
 		return -EINVAL;
 
 	local_irq_save(flags);
 
-	slpcon = __raw_readl(base + 0x0C);
+	slpcon = __raw_readl(chip->base + 0x0C);
 
 	slpcon &= ~(3 << offs);
 	slpcon |= state << offs;
 
-	__raw_writel(slpcon, base + 0x0C);
+	__raw_writel(slpcon, chip->base + 0x0C);
 
 	local_irq_restore(flags);
 
diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c
index 4316018..478f4b4 100644
--- a/arch/arm/mach-s3c2412/mach-jive.c
+++ b/arch/arm/mach-s3c2412/mach-jive.c
@@ -674,7 +674,7 @@
 }
 
 MACHINE_START(JIVE, "JIVE")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index faddb36..ba93a35 100644
--- a/arch/arm/mach-s3c2412/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -150,7 +150,7 @@
 }
 
 MACHINE_START(S3C2413, "S3C2413")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
@@ -163,7 +163,7 @@
 MACHINE_END
 
 MACHINE_START(SMDK2412, "SMDK2412")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
@@ -176,7 +176,7 @@
 MACHINE_END
 
 MACHINE_START(SMDK2413, "SMDK2413")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
index 9d102b9..cd8e7de 100644
--- a/arch/arm/mach-s3c2440/Kconfig
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -188,4 +188,17 @@
 	  Say Y here to select support for the MINI2440. Is a 10cm x 10cm board
 	  available via various sources. It can come with a 3.5" or 7" touch LCD.
 
+config MACH_RX1950
+	bool "HP iPAQ rx1950"
+	select CPU_S3C2442
+	select S3C24XX_DCLK
+	select PM_H1940 if PM
+	select I2C
+	select S3C2410_PWM
+	select S3C_DEV_NAND
+	select S3C2410_IOTIMING if S3C2440_CPUFREQ
+	select S3C2440_XTAL_16934400
+	help
+	   Say Y here if you're using HP iPAQ rx1950
+
 endmenu
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
index c85ba32..d5440fa 100644
--- a/arch/arm/mach-s3c2440/Makefile
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -34,6 +34,7 @@
 obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
 obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o
 obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
+obj-$(CONFIG_MACH_RX1950) += mach-rx1950.o
 
 # extra machine support
 
diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c
new file mode 100644
index 0000000..8603b57
--- /dev/null
+++ b/arch/arm/mach-s3c2440/mach-rx1950.c
@@ -0,0 +1,582 @@
+/* linux/arch/arm/mach-s3c2440/mach-rx1950.c
+ *
+ * Copyright (c) 2006-2009 Victor Chukhantsev, Denis Grigoriev,
+ * Copyright (c) 2007-2010 Vasily Khoruzhick
+ *
+ * based on smdk2440 written by Ben Dooks
+ *
+ * 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/delay.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/sysdev.h>
+#include <linux/pwm_backlight.h>
+#include <linux/pwm.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/mmc/host.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+#include <mach/regs-gpio.h>
+#include <mach/regs-gpioj.h>
+#include <mach/h1940.h>
+#include <mach/fb.h>
+
+#include <plat/clock.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-iic.h>
+#include <plat/mci.h>
+#include <plat/udc.h>
+#include <plat/nand.h>
+#include <plat/iic.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/pm.h>
+#include <plat/irq.h>
+#include <plat/ts.h>
+
+#define LCD_PWM_PERIOD 192960
+#define LCD_PWM_DUTY 127353
+
+static struct map_desc rx1950_iodesc[] __initdata = {
+};
+
+static struct s3c24xx_uart_clksrc rx1950_serial_clocks[] = {
+	[0] = {
+	       .name = "fclk",
+	       .divisor = 0x0a,
+	       .min_baud = 0,
+	       .max_baud = 0,
+	},
+};
+
+static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = {
+	[0] = {
+	       .hwport = 0,
+	       .flags = 0,
+	       .ucon = 0x3c5,
+	       .ulcon = 0x03,
+	       .ufcon = 0x51,
+	       .clocks = rx1950_serial_clocks,
+	       .clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
+	},
+	[1] = {
+	       .hwport = 1,
+	       .flags = 0,
+	       .ucon = 0x3c5,
+	       .ulcon = 0x03,
+	       .ufcon = 0x51,
+	       .clocks = rx1950_serial_clocks,
+	       .clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
+	},
+	/* IR port */
+	[2] = {
+	       .hwport = 2,
+	       .flags = 0,
+	       .ucon = 0x3c5,
+	       .ulcon = 0x43,
+	       .ufcon = 0xf1,
+	       .clocks = rx1950_serial_clocks,
+	       .clocks_size = ARRAY_SIZE(rx1950_serial_clocks),
+	},
+};
+
+static struct s3c2410fb_display rx1950_display = {
+	.type = S3C2410_LCDCON1_TFT,
+	.width = 240,
+	.height = 320,
+	.xres = 240,
+	.yres = 320,
+	.bpp = 16,
+
+	.pixclock = 260000,
+	.left_margin = 10,
+	.right_margin = 20,
+	.hsync_len = 10,
+	.upper_margin = 2,
+	.lower_margin = 2,
+	.vsync_len = 2,
+
+	.lcdcon5 = S3C2410_LCDCON5_FRM565 |
+			   S3C2410_LCDCON5_INVVCLK |
+			   S3C2410_LCDCON5_INVVLINE |
+			   S3C2410_LCDCON5_INVVFRAME |
+			   S3C2410_LCDCON5_HWSWP |
+			   (0x02 << 13) |
+			   (0x02 << 15),
+
+};
+
+static struct s3c2410fb_mach_info rx1950_lcd_cfg = {
+	.displays = &rx1950_display,
+	.num_displays = 1,
+	.default_display = 0,
+
+	.lpcsel = 0x02,
+	.gpccon = 0xaa9556a9,
+	.gpccon_mask = 0xffc003fc,
+	.gpcup = 0x0000ffff,
+	.gpcup_mask = 0xffffffff,
+
+	.gpdcon = 0xaa90aaa1,
+	.gpdcon_mask = 0xffc0fff0,
+	.gpdup = 0x0000fcfd,
+	.gpdup_mask = 0xffffffff,
+
+};
+
+static struct pwm_device *lcd_pwm;
+
+void rx1950_lcd_power(int enable)
+{
+	int i;
+	static int enabled;
+	if (enabled == enable)
+		return;
+	if (!enable) {
+
+		/* GPC11-GPC15->OUTPUT */
+		for (i = 11; i < 16; i++)
+			gpio_direction_output(S3C2410_GPC(i), 1);
+
+		/* Wait a bit here... */
+		mdelay(100);
+
+		/* GPD2-GPD7->OUTPUT */
+		/* GPD11-GPD15->OUTPUT */
+		/* GPD2-GPD7->1, GPD11-GPD15->1 */
+		for (i = 2; i < 8; i++)
+			gpio_direction_output(S3C2410_GPD(i), 1);
+		for (i = 11; i < 16; i++)
+			gpio_direction_output(S3C2410_GPD(i), 1);
+
+		/* Wait a bit here...*/
+		mdelay(100);
+
+		/* GPB0->OUTPUT, GPB0->0 */
+		gpio_direction_output(S3C2410_GPB(0), 0);
+
+		/* GPC1-GPC4->OUTPUT, GPC1-4->0 */
+		for (i = 1; i < 5; i++)
+			gpio_direction_output(S3C2410_GPC(i), 0);
+
+		/* GPC15-GPC11->0 */
+		for (i = 11; i < 16; i++)
+			gpio_direction_output(S3C2410_GPC(i), 0);
+
+		/* GPD15-GPD11->0, GPD2->GPD7->0 */
+		for (i = 11; i < 16; i++)
+			gpio_direction_output(S3C2410_GPD(i), 0);
+
+		for (i = 2; i < 8; i++)
+			gpio_direction_output(S3C2410_GPD(i), 0);
+
+		/* GPC6->0, GPC7->0, GPC5->0 */
+		gpio_direction_output(S3C2410_GPC(6), 0);
+		gpio_direction_output(S3C2410_GPC(7), 0);
+		gpio_direction_output(S3C2410_GPC(5), 0);
+
+		/* GPB1->OUTPUT, GPB1->0 */
+		gpio_direction_output(S3C2410_GPB(1), 0);
+		pwm_config(lcd_pwm, 0, LCD_PWM_PERIOD);
+		pwm_disable(lcd_pwm);
+
+		/* GPC0->0, GPC10->0 */
+		gpio_direction_output(S3C2410_GPC(0), 0);
+		gpio_direction_output(S3C2410_GPC(10), 0);
+	} else {
+		pwm_config(lcd_pwm, LCD_PWM_DUTY, LCD_PWM_PERIOD);
+		pwm_enable(lcd_pwm);
+
+		gpio_direction_output(S3C2410_GPC(0), 1);
+		gpio_direction_output(S3C2410_GPC(5), 1);
+
+		s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPB1_TOUT1);
+		gpio_direction_output(S3C2410_GPC(7), 1);
+
+		for (i = 1; i < 5; i++)
+			s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
+
+		for (i = 11; i < 16; i++)
+			s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2));
+
+		for (i = 2; i < 8; i++)
+			s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
+
+		for (i = 11; i < 16; i++)
+			s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2));
+
+		gpio_direction_output(S3C2410_GPC(10), 1);
+		gpio_direction_output(S3C2410_GPC(6), 1);
+	}
+	enabled = enable;
+}
+
+static void rx1950_bl_power(int enable)
+{
+	static int enabled;
+	if (enabled == enable)
+		return;
+	if (!enable) {
+			gpio_direction_output(S3C2410_GPB(0), 0);
+	} else {
+			/* LED driver need a "push" to power on */
+			gpio_direction_output(S3C2410_GPB(0), 1);
+			/* Warm up backlight for one period of PWM.
+			 * Without this trick its almost impossible to
+			 * enable backlight with low brightness value
+			 */
+			ndelay(48000);
+			s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
+	}
+	enabled = enable;
+}
+
+static int rx1950_backlight_init(struct device *dev)
+{
+	WARN_ON(gpio_request(S3C2410_GPB(0), "Backlight"));
+	lcd_pwm = pwm_request(1, "RX1950 LCD");
+	if (IS_ERR(lcd_pwm)) {
+		dev_err(dev, "Unable to request PWM for LCD power!\n");
+		return PTR_ERR(lcd_pwm);
+	}
+
+	rx1950_lcd_power(1);
+	rx1950_bl_power(1);
+
+	return 0;
+}
+
+static void rx1950_backlight_exit(struct device *dev)
+{
+	rx1950_bl_power(0);
+	rx1950_lcd_power(0);
+
+	pwm_free(lcd_pwm);
+	gpio_free(S3C2410_GPB(0));
+}
+
+
+static int rx1950_backlight_notify(struct device *dev, int brightness)
+{
+	if (!brightness) {
+		rx1950_bl_power(0);
+		rx1950_lcd_power(0);
+	} else {
+		rx1950_lcd_power(1);
+		rx1950_bl_power(1);
+	}
+	return brightness;
+}
+
+static struct platform_pwm_backlight_data rx1950_backlight_data = {
+	.pwm_id = 0,
+	.max_brightness = 24,
+	.dft_brightness = 4,
+	.pwm_period_ns = 48000,
+	.init = rx1950_backlight_init,
+	.notify = rx1950_backlight_notify,
+	.exit = rx1950_backlight_exit,
+};
+
+static struct platform_device rx1950_backlight = {
+	.name = "pwm-backlight",
+	.dev = {
+		.parent = &s3c_device_timer[0].dev,
+		.platform_data = &rx1950_backlight_data,
+	},
+};
+
+static void rx1950_set_mmc_power(unsigned char power_mode, unsigned short vdd)
+{
+	switch (power_mode) {
+	case MMC_POWER_OFF:
+		gpio_direction_output(S3C2410_GPJ(1), 0);
+		break;
+	case MMC_POWER_UP:
+	case MMC_POWER_ON:
+		gpio_direction_output(S3C2410_GPJ(1), 1);
+		break;
+	default:
+		break;
+	}
+}
+
+static struct s3c24xx_mci_pdata rx1950_mmc_cfg __initdata = {
+	.gpio_detect = S3C2410_GPF(5),
+	.gpio_wprotect = S3C2410_GPH(8),
+	.set_power = rx1950_set_mmc_power,
+	.ocr_avail = MMC_VDD_32_33,
+};
+
+static struct mtd_partition rx1950_nand_part[] = {
+	[0] = {
+			.name = "Boot0",
+			.offset = 0,
+			.size = 0x4000,
+			.mask_flags = MTD_WRITEABLE,
+	},
+	[1] = {
+			.name = "Boot1",
+			.offset = MTDPART_OFS_APPEND,
+			.size = 0x40000,
+			.mask_flags = MTD_WRITEABLE,
+	},
+	[2] = {
+			.name = "Kernel",
+			.offset = MTDPART_OFS_APPEND,
+			.size = 0x300000,
+			.mask_flags = 0,
+	},
+	[3] = {
+			.name = "Filesystem",
+			.offset = MTDPART_OFS_APPEND,
+			.size = MTDPART_SIZ_FULL,
+			.mask_flags = 0,
+	},
+};
+
+static struct s3c2410_nand_set rx1950_nand_sets[] = {
+	[0] = {
+			.name = "Internal",
+			.nr_chips = 1,
+			.nr_partitions = ARRAY_SIZE(rx1950_nand_part),
+			.partitions = rx1950_nand_part,
+	},
+};
+
+static struct s3c2410_platform_nand rx1950_nand_info = {
+	.tacls = 25,
+	.twrph0 = 50,
+	.twrph1 = 15,
+	.nr_sets = ARRAY_SIZE(rx1950_nand_sets),
+	.sets = rx1950_nand_sets,
+};
+
+static void rx1950_udc_pullup(enum s3c2410_udc_cmd_e cmd)
+{
+	switch (cmd) {
+	case S3C2410_UDC_P_ENABLE:
+		gpio_direction_output(S3C2410_GPJ(5), 1);
+		break;
+	case S3C2410_UDC_P_DISABLE:
+		gpio_direction_output(S3C2410_GPJ(5), 0);
+		break;
+	case S3C2410_UDC_P_RESET:
+		break;
+	default:
+		break;
+	}
+}
+
+static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
+	.udc_command = rx1950_udc_pullup,
+	.vbus_pin = S3C2410_GPG(5),
+	.vbus_pin_inverted = 1,
+};
+
+static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = {
+	.delay = 10000,
+	.presc = 49,
+	.oversampling_shift = 3,
+};
+
+static struct gpio_keys_button rx1950_gpio_keys_table[] = {
+	{
+		.code		= KEY_POWER,
+		.gpio		= S3C2410_GPF(0),
+		.active_low	= 1,
+		.desc		= "Power button",
+		.wakeup		= 1,
+	},
+	{
+		.code		= KEY_F5,
+		.gpio		= S3C2410_GPF(7),
+		.active_low	= 1,
+		.desc		= "Record button",
+	},
+	{
+		.code		= KEY_F1,
+		.gpio		= S3C2410_GPG(0),
+		.active_low	= 1,
+		.desc		= "Calendar button",
+	},
+	{
+		.code		= KEY_F2,
+		.gpio		= S3C2410_GPG(2),
+		.active_low	= 1,
+		.desc		= "Contacts button",
+	},
+	{
+		.code		= KEY_F3,
+		.gpio		= S3C2410_GPG(3),
+		.active_low	= 1,
+		.desc		= "Mail button",
+	},
+	{
+		.code		= KEY_F4,
+		.gpio		= S3C2410_GPG(7),
+		.active_low	= 1,
+		.desc		= "WLAN button",
+	},
+	{
+		.code		= KEY_LEFT,
+		.gpio		= S3C2410_GPG(10),
+		.active_low	= 1,
+		.desc		= "Left button",
+	},
+	{
+		.code		= KEY_RIGHT,
+		.gpio		= S3C2410_GPG(11),
+		.active_low	= 1,
+		.desc		= "Right button",
+	},
+	{
+		.code		= KEY_UP,
+		.gpio		= S3C2410_GPG(4),
+		.active_low	= 1,
+		.desc		= "Up button",
+	},
+	{
+		.code		= KEY_DOWN,
+		.gpio		= S3C2410_GPG(6),
+		.active_low	= 1,
+		.desc		= "Down button",
+	},
+	{
+		.code		= KEY_ENTER,
+		.gpio		= S3C2410_GPG(9),
+		.active_low	= 1,
+		.desc		= "Ok button"
+	},
+};
+
+static struct gpio_keys_platform_data rx1950_gpio_keys_data = {
+	.buttons = rx1950_gpio_keys_table,
+	.nbuttons = ARRAY_SIZE(rx1950_gpio_keys_table),
+};
+
+static struct platform_device rx1950_device_gpiokeys = {
+	.name = "gpio-keys",
+	.dev.platform_data = &rx1950_gpio_keys_data,
+};
+
+static struct s3c2410_platform_i2c rx1950_i2c_data = {
+	.flags = 0,
+	.slave_addr = 0x42,
+	.frequency = 400 * 1000,
+	.sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
+};
+
+static struct platform_device *rx1950_devices[] __initdata = {
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c0,
+	&s3c_device_iis,
+	&s3c_device_usbgadget,
+	&s3c_device_rtc,
+	&s3c_device_nand,
+	&s3c_device_sdi,
+	&s3c_device_adc,
+	&s3c_device_ts,
+	&s3c_device_timer[0],
+	&s3c_device_timer[1],
+	&rx1950_backlight,
+	&rx1950_device_gpiokeys,
+};
+
+static struct clk *rx1950_clocks[] __initdata = {
+	&s3c24xx_clkout0,
+	&s3c24xx_clkout1,
+};
+
+static void __init rx1950_map_io(void)
+{
+	s3c24xx_clkout0.parent  = &clk_h;
+	s3c24xx_clkout1.parent  = &clk_f;
+
+	s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks));
+
+	s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
+	s3c24xx_init_clocks(16934000);
+	s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
+
+	/* setup PM */
+
+#ifdef CONFIG_PM_H1940
+	memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 8);
+#endif
+
+	s3c_pm_init();
+}
+
+static void __init rx1950_init_machine(void)
+{
+	int i;
+
+	s3c24xx_fb_set_platdata(&rx1950_lcd_cfg);
+	s3c24xx_udc_set_platdata(&rx1950_udc_cfg);
+	s3c24xx_ts_set_platdata(&rx1950_ts_cfg);
+	s3c24xx_mci_set_platdata(&rx1950_mmc_cfg);
+	s3c_i2c0_set_platdata(&rx1950_i2c_data);
+	s3c_nand_set_platdata(&rx1950_nand_info);
+
+	/* Turn off suspend on both USB ports, and switch the
+	 * selectable USB port to USB device mode. */
+	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
+						S3C2410_MISCCR_USBSUSPND0 |
+						S3C2410_MISCCR_USBSUSPND1, 0x0);
+
+	WARN_ON(gpio_request(S3C2410_GPJ(5), "UDC pullup"));
+	gpio_direction_output(S3C2410_GPJ(5), 0);
+
+	/* mmc power is disabled by default */
+	WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power"));
+	gpio_direction_output(S3C2410_GPJ(1), 0);
+
+	for (i = 0; i < 8; i++)
+		WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
+
+	for (i = 10; i < 16; i++)
+		WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power"));
+
+	for (i = 2; i < 8; i++)
+		WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
+
+	for (i = 11; i < 16; i++)
+		WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power"));
+
+	WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power"));
+
+	platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
+}
+
+MACHINE_START(RX1950, "HP iPAQ RX1950")
+    /* Maintainers: Vasily Khoruzhick */
+    .phys_io = S3C2410_PA_UART,
+	.io_pg_offst = (((u32) S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params = S3C2410_SDRAM_PA + 0x100,
+	.map_io = rx1950_map_io,
+	.init_irq = s3c24xx_init_irq,
+	.init_machine = rx1950_init_machine,
+	.timer = &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index 1e836e5..d2946de 100644
--- a/arch/arm/mach-s3c2440/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -209,7 +209,7 @@
 }
 
 MACHINE_START(RX3715, "IPAQ-RX3715")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index 3ac3d63..df83276 100644
--- a/arch/arm/mach-s3c2440/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -174,7 +174,7 @@
 }
 
 MACHINE_START(S3C2440, "SMDK2440")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
index e2e362b..4c863d3 100644
--- a/arch/arm/mach-s3c2443/mach-smdk2443.c
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -131,7 +131,7 @@
 }
 
 MACHINE_START(SMDK2443, "SMDK2443")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C2410_SDRAM_PA + 0x100,
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 2ac2e7d..7a4138b 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -88,6 +88,12 @@
 	.enable		= clk_48m_ctrl,
 };
 
+struct clk clk_xusbxti = {
+	.name		= "xusbxti",
+	.id		= -1,
+	.rate		= 48000000,
+};
+
 static int inline s3c64xx_gate(void __iomem *reg,
 				struct clk *clk,
 				int enable)
@@ -518,6 +524,11 @@
 	.id		= -1,
 };
 
+static struct clk clk_iisv4_cd = {
+	.name		= "iis_cdclk_v4",
+	.id		= -1,
+};
+
 static struct clk clk_pcm_cd = {
 	.name		= "pcm_cdclk",
 	.id		= -1,
@@ -549,6 +560,19 @@
 	.nr_sources	= ARRAY_SIZE(clkset_audio1_list),
 };
 
+static struct clk *clkset_audio2_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_dout_mpll,
+	[2] = &clk_fin_epll,
+	[3] = &clk_iisv4_cd,
+	[4] = &clk_pcm_cd,
+};
+
+static struct clksrc_sources clkset_audio2 = {
+	.sources	= clkset_audio2_list,
+	.nr_sources	= ARRAY_SIZE(clkset_audio2_list),
+};
+
 static struct clk *clkset_camif_list[] = {
 	&clk_h2,
 };
@@ -652,6 +676,16 @@
 		.sources	= &clkset_audio1,
 	}, {
 		.clk	= {
+			.name		= "audio-bus",
+			.id		= -1,  /* There's only one IISv4 port */
+			.ctrlbit        = S3C6410_CLKCON_SCLK_AUDIO2,
+			.enable		= s3c64xx_sclk_ctrl,
+		},
+		.reg_src	= { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3  },
+		.reg_div	= { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4  },
+		.sources	= &clkset_audio2,
+	}, {
+		.clk	= {
 			.name		= "irda-bus",
 			.id		= 0,
 			.ctrlbit        = S3C_CLKCON_SCLK_IRDA,
@@ -749,6 +783,7 @@
 	&clk_ext_xtal_mux,
 	&clk_iis_cd0,
 	&clk_iis_cd1,
+	&clk_iisv4_cd,
 	&clk_pcm_cd,
 	&clk_mout_epll.clk,
 	&clk_mout_mpll.clk,
@@ -762,6 +797,7 @@
 	&clk_27m,
 	&clk_48m,
 	&clk_h2,
+	&clk_xusbxti,
 };
 
 /**
diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c
index 33ccf7b..5567e03 100644
--- a/arch/arm/mach-s3c64xx/dma.c
+++ b/arch/arm/mach-s3c64xx/dma.c
@@ -414,7 +414,7 @@
 EXPORT_SYMBOL(s3c2410_dma_enqueue);
 
 
-int s3c2410_dma_devconfig(int channel,
+int s3c2410_dma_devconfig(unsigned int channel,
 			  enum s3c2410_dmasrc source,
 			  unsigned long devaddr)
 {
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
index 3ef6274..0114eb0 100644
--- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h
@@ -33,6 +33,7 @@
 #define S3C_PCLK_GATE		S3C_CLKREG(0x34)
 #define S3C_SCLK_GATE		S3C_CLKREG(0x38)
 #define S3C_MEM0_GATE		S3C_CLKREG(0x3C)
+#define S3C6410_CLK_SRC2	S3C_CLKREG(0x10C)
 
 /* CLKDIV0 */
 #define S3C6400_CLKDIV0_PCLK_MASK	(0xf << 12)
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index f7b1898..5991667 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -84,7 +84,7 @@
 }
 
 MACHINE_START(SMDK6400, "SMDK6400")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C_PA_UART & 0xfff00000,
 	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 2d5afd2..9d51455 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -656,7 +656,7 @@
 }
 
 MACHINE_START(SMDK6410, "SMDK6410")
-	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	/* Maintainer: Ben Dooks <ben-linux@fluff.org> */
 	.phys_io	= S3C_PA_UART & 0xfff00000,
 	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
 	.boot_params	= S3C64XX_PA_SDRAM + 0x100,
diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c
index b2672e1..ca6e48d 100644
--- a/arch/arm/mach-s5p6440/clock.c
+++ b/arch/arm/mach-s5p6440/clock.c
@@ -134,24 +134,6 @@
 	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 },
 };
 
-static struct clk clk_h_low = {
-	.name		= "hclk_low",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-	.ops		= &clk_ops_def_setrate,
-};
-
-static struct clk clk_p_low = {
-	.name		= "pclk_low",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-	.ops		= &clk_ops_def_setrate,
-};
-
 enum perf_level {
 	L0 = 532*1000,
 	L1 = 266*1000,
@@ -247,23 +229,70 @@
 	.round_rate	= s5p6440_armclk_round_rate,
 };
 
-static unsigned long s5p6440_clk_doutmpll_get_rate(struct clk *clk)
-{
-	unsigned long rate = clk_get_rate(clk->parent);
-
-	if (__raw_readl(S5P_CLK_DIV0) & S5P_CLKDIV0_MPLL_MASK)
-		rate /= 2;
-
-	return rate;
-}
-
-static struct clk clk_dout_mpll = {
-	.name		= "dout_mpll",
-	.id		= -1,
-	.parent		= &clk_mout_mpll.clk,
-	.ops            = &(struct clk_ops) {
-		.get_rate	= s5p6440_clk_doutmpll_get_rate,
+static struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name	= "armclk",
+		.id	= 1,
+		.parent	= &clk_mout_apll.clk,
+		.ops	= &s5p6440_clkarm_ops,
 	},
+	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mpll = {
+	.clk	= {
+		.name	= "dout_mpll",
+		.id	= -1,
+		.parent	= &clk_mout_mpll.clk,
+	},
+	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_hclk = {
+	.clk	= {
+		.name	= "clk_hclk",
+		.id	= -1,
+		.parent	= &clk_armclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk = {
+	.clk	= {
+		.name	= "clk_pclk",
+		.id	= -1,
+		.parent	= &clk_hclk.clk,
+	},
+	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 },
+};
+
+static struct clk *clkset_hclklow_list[] = {
+	&clk_mout_apll.clk,
+	&clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_hclklow = {
+	.sources	= clkset_hclklow_list,
+	.nr_sources	= ARRAY_SIZE(clkset_hclklow_list),
+};
+
+static struct clksrc_clk clk_hclk_low = {
+	.clk = {
+		.name	= "hclk_low",
+		.id	= -1,
+	},
+	.sources	= &clkset_hclklow,
+	.reg_src	= { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 },
+	.reg_div	= { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_low = {
+	.clk	= {
+		.name	= "pclk_low",
+		.id	= -1,
+		.parent	= &clk_hclk_low.clk,
+	},
+	.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
 };
 
 int s5p6440_clk48m_ctrl(struct clk *clk, int enable)
@@ -307,6 +336,11 @@
 	return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable);
 }
 
+static int s5p6440_sclk1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable);
+}
+
 static int s5p6440_mem_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable);
@@ -321,37 +355,37 @@
 	{
 		.name		= "nand",
 		.id		= -1,
-		.parent		= &clk_h,
+		.parent		= &clk_hclk.clk,
 		.enable		= s5p6440_mem_ctrl,
 		.ctrlbit	= S5P_CLKCON_MEM0_HCLK_NFCON,
 	}, {
 		.name		= "adc",
 		.id		= -1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_TSADC,
 	}, {
 		.name		= "i2c",
 		.id		= -1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_IIC0,
 	}, {
 		.name		= "i2s_v40",
 		.id		= 0,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_IIS2,
 	}, {
 		.name		= "spi",
 		.id		= 0,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_SPI0,
 	}, {
 		.name		= "spi",
 		.id		= 1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_SPI1,
 	}, {
@@ -387,58 +421,124 @@
 	}, {
 		.name    	= "otg",
 		.id	   	= -1,
-		.parent  	= &clk_h_low,
+		.parent		= &clk_hclk_low.clk,
 		.enable  	= s5p6440_hclk0_ctrl,
 		.ctrlbit 	= S5P_CLKCON_HCLK0_USB
 	}, {
 		.name    	= "post",
 		.id	   	= -1,
-		.parent  	= &clk_h_low,
+		.parent		= &clk_hclk_low.clk,
 		.enable  	= s5p6440_hclk0_ctrl,
 		.ctrlbit 	= S5P_CLKCON_HCLK0_POST0
 	}, {
 		.name		= "lcd",
 		.id		= -1,
-		.parent		= &clk_h_low,
+		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p6440_hclk1_ctrl,
 		.ctrlbit	= S5P_CLKCON_HCLK1_DISPCON,
 	}, {
 		.name		= "hsmmc",
 		.id		= 0,
-		.parent		= &clk_h_low,
+		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p6440_hclk0_ctrl,
 		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC0,
 	}, {
 		.name		= "hsmmc",
 		.id		= 1,
-		.parent		= &clk_h_low,
+		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p6440_hclk0_ctrl,
 		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC1,
 	}, {
 		.name		= "hsmmc",
 		.id		= 2,
-		.parent		= &clk_h_low,
+		.parent		= &clk_hclk_low.clk,
 		.enable		= s5p6440_hclk0_ctrl,
 		.ctrlbit	= S5P_CLKCON_HCLK0_HSMMC2,
 	}, {
 		.name		= "rtc",
 		.id		= -1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_RTC,
 	}, {
 		.name		= "watchdog",
 		.id		= -1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_WDT,
 	}, {
 		.name		= "timers",
 		.id		= -1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_PWM,
-	}
+	}, {
+		.name		= "hclk_fimgvg",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p6440_hclk1_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "tsi",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p6440_hclk1_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "pclk_fimgvg",
+		.id		= -1,
+		.parent		= &clk_pclk.clk,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= (1 << 31),
+	}, {
+		.name		= "dmc0",
+		.id		= -1,
+		.parent		= &clk_pclk.clk,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= (1 << 30),
+	}, {
+		.name		= "etm",
+		.id		= -1,
+		.parent		= &clk_pclk.clk,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= (1 << 29),
+	}, {
+		.name		= "dsim",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= (1 << 28),
+	}, {
+		.name		= "gps",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= (1 << 25),
+	}, {
+		.name		= "pcm",
+		.id		= -1,
+		.parent		= &clk_pclk_low.clk,
+		.enable		= s5p6440_pclk_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "irom",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= (1 << 25),
+	}, {
+		.name		= "dma",
+		.id		= -1,
+		.parent		= &clk_hclk_low.clk,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "2d",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= (1 << 8),
+	},
 };
 
 /*
@@ -448,34 +548,46 @@
 	{
 		.name		= "gpio",
 		.id		= -1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_GPIO,
 	}, {
 		.name		= "uart",
 		.id		= 0,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_UART0,
 	}, {
 		.name		= "uart",
 		.id		= 1,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_UART1,
 	}, {
 		.name		= "uart",
 		.id		= 2,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_UART2,
 	}, {
 		.name		= "uart",
 		.id		= 3,
-		.parent		= &clk_p_low,
+		.parent		= &clk_pclk_low.clk,
 		.enable		= s5p6440_pclk_ctrl,
 		.ctrlbit	= S5P_CLKCON_PCLK_UART3,
-	}
+	}, {
+		.name		= "mem",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "intc",
+		.id		= -1,
+		.parent		= &clk_hclk.clk,
+		.enable		= s5p6440_hclk0_ctrl,
+		.ctrlbit	= (1 << 1),
+	},
 };
 
 static struct clk clk_iis_cd_v40 = {
@@ -488,20 +600,20 @@
 	.id		= -1,
 };
 
-static struct clk *clkset_spi_mmc_list[] = {
+static struct clk *clkset_group1_list[] = {
 	&clk_mout_epll.clk,
-	&clk_dout_mpll,
+	&clk_dout_mpll.clk,
 	&clk_fin_epll,
 };
 
-static struct clksrc_sources clkset_spi_mmc = {
-	.sources	= clkset_spi_mmc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_spi_mmc_list),
+static struct clksrc_sources clkset_group1 = {
+	.sources	= clkset_group1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group1_list),
 };
 
 static struct clk *clkset_uart_list[] = {
 	&clk_mout_epll.clk,
-	&clk_dout_mpll
+	&clk_dout_mpll.clk,
 };
 
 static struct clksrc_sources clkset_uart = {
@@ -509,6 +621,19 @@
 	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
 };
 
+static struct clk *clkset_audio_list[] = {
+	&clk_mout_epll.clk,
+	&clk_dout_mpll.clk,
+	&clk_fin_epll,
+	&clk_iis_cd_v40,
+	&clk_pcm_cd,
+};
+
+static struct clksrc_sources clkset_audio = {
+	.sources	= clkset_audio_list,
+	.nr_sources	= ARRAY_SIZE(clkset_audio_list),
+};
+
 static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
@@ -517,7 +642,7 @@
 			.ctrlbit        = S5P_CLKCON_SCLK0_MMC0,
 			.enable		= s5p6440_sclk_ctrl,
 		},
-		.sources = &clkset_spi_mmc,
+		.sources = &clkset_group1,
 		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 },
 		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 },
 	}, {
@@ -527,7 +652,7 @@
 			.ctrlbit        = S5P_CLKCON_SCLK0_MMC1,
 			.enable		= s5p6440_sclk_ctrl,
 		},
-		.sources = &clkset_spi_mmc,
+		.sources = &clkset_group1,
 		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 },
 		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 },
 	}, {
@@ -537,7 +662,7 @@
 			.ctrlbit        = S5P_CLKCON_SCLK0_MMC2,
 			.enable		= s5p6440_sclk_ctrl,
 		},
-		.sources = &clkset_spi_mmc,
+		.sources = &clkset_group1,
 		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 },
 		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 },
 	}, {
@@ -557,7 +682,7 @@
 			.ctrlbit        = S5P_CLKCON_SCLK0_SPI0,
 			.enable		= s5p6440_sclk_ctrl,
 		},
-		.sources = &clkset_spi_mmc,
+		.sources = &clkset_group1,
 		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 },
 		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
 	}, {
@@ -567,17 +692,63 @@
 			.ctrlbit        = S5P_CLKCON_SCLK0_SPI1,
 			.enable		= s5p6440_sclk_ctrl,
 		},
-		.sources = &clkset_spi_mmc,
+		.sources = &clkset_group1,
 		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 },
 		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
-	}
+	}, {
+		.clk	= {
+			.name		= "sclk_post",
+			.id		= -1,
+			.ctrlbit	= (1 << 10),
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_dispcon",
+			.id		= -1,
+			.ctrlbit	= (1 << 1),
+			.enable		= s5p6440_sclk1_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_fimgvg",
+			.id		= -1,
+			.ctrlbit	= (1 << 2),
+			.enable		= s5p6440_sclk1_ctrl,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_audio2",
+			.id		= -1,
+			.ctrlbit	= (1 << 11),
+			.enable		= s5p6440_sclk_ctrl,
+		},
+		.sources = &clkset_audio,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 },
+		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 },
+	},
 };
 
 /* Clock initialisation code */
-static struct clksrc_clk *init_parents[] = {
+static struct clksrc_clk *sysclks[] = {
 	&clk_mout_apll,
 	&clk_mout_epll,
 	&clk_mout_mpll,
+	&clk_dout_mpll,
+	&clk_armclk,
+	&clk_hclk,
+	&clk_pclk,
+	&clk_hclk_low,
+	&clk_pclk_low,
 };
 
 void __init_or_cpufreq s5p6440_setup_clocks(void)
@@ -593,21 +764,13 @@
 	unsigned long apll;
 	unsigned long mpll;
 	unsigned int ptr;
-	u32 clkdiv0;
-	u32 clkdiv3;
 
 	/* Set S5P6440 functions for clk_fout_epll */
 	clk_fout_epll.enable = s5p6440_epll_enable;
 	clk_fout_epll.ops = &s5p6440_epll_ops;
 
-	/* Set S5P6440 functions for arm clock */
-	clk_arm.parent = &clk_mout_apll.clk;
-	clk_arm.ops = &s5p6440_clkarm_ops;
 	clk_48m.enable = s5p6440_clk48m_ctrl;
 
-	clkdiv0 = __raw_readl(S5P_CLK_DIV0);
-	clkdiv3 = __raw_readl(S5P_CLK_DIV3);
-
 	xtal_clk = clk_get(NULL, "ext_xtal");
 	BUG_ON(IS_ERR(xtal_clk));
 
@@ -619,41 +782,28 @@
 	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
 	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502);
 
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_apll.rate = apll;
+
 	printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \
 			" E=%ld.%ldMHz\n",
 			print_mhz(apll), print_mhz(mpll), print_mhz(epll));
 
-	fclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_ARM);
-	hclk = fclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK);
-	pclk = hclk / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK);
-
-	if (__raw_readl(S5P_OTHERS) & S5P_OTHERS_HCLK_LOW_SEL_MPLL) {
-		/* Asynchronous mode */
-		hclk_low = mpll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
-	} else {
-		/* Synchronous mode */
-		hclk_low = apll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW);
-	}
-
-	pclk_low = hclk_low / GET_DIV(clkdiv3, S5P_CLKDIV3_PCLK_LOW);
+	fclk = clk_get_rate(&clk_armclk.clk);
+	hclk = clk_get_rate(&clk_hclk.clk);
+	pclk = clk_get_rate(&clk_pclk.clk);
+	hclk_low = clk_get_rate(&clk_hclk_low.clk);
+	pclk_low = clk_get_rate(&clk_pclk_low.clk);
 
 	printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \
 			" PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n",
 			print_mhz(hclk), print_mhz(hclk_low),
 			print_mhz(pclk), print_mhz(pclk_low));
 
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_apll.rate = apll;
-
 	clk_f.rate = fclk;
 	clk_h.rate = hclk;
 	clk_p.rate = pclk;
-	clk_h_low.rate = hclk_low;
-	clk_p_low.rate = pclk_low;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
-		s3c_set_clksrc(init_parents[ptr], true);
 
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 		s3c_set_clksrc(&clksrcs[ptr], true);
@@ -661,13 +811,8 @@
 
 static struct clk *clks[] __initdata = {
 	&clk_ext,
-	&clk_mout_epll.clk,
-	&clk_mout_mpll.clk,
-	&clk_dout_mpll,
 	&clk_iis_cd_v40,
 	&clk_pcm_cd,
-	&clk_p_low,
-	&clk_h_low,
 };
 
 void __init s5p6440_register_clocks(void)
@@ -680,6 +825,9 @@
 	if (ret > 0)
 		printk(KERN_ERR "Failed to register %u clocks\n", ret);
 
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c
index 1794131a..ca3b320 100644
--- a/arch/arm/mach-s5p6440/cpu.c
+++ b/arch/arm/mach-s5p6440/cpu.c
@@ -88,7 +88,7 @@
 	s5p_init_irq(vic, ARRAY_SIZE(vic));
 }
 
-static struct sysdev_class s5p6440_sysclass = {
+struct sysdev_class s5p6440_sysclass = {
 	.name	= "s5p6440-core",
 };
 
diff --git a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h b/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
index c4bb7c5..6a2a02f 100644
--- a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
+++ b/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
@@ -1,11 +1,14 @@
 /* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h
  *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *      Ben Dooks <ben@simtec.co.uk>
  *      http://armlinux.simtec.co.uk/
  *
- * Copyright 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
+ * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
  *
  * S5P6440 - pwm clock and timer support
  *
@@ -14,16 +17,19 @@
  * published by the Free Software Foundation.
 */
 
+#ifndef __ASM_ARCH_PWMCLK_H
+#define __ASM_ARCH_PWMCLK_H __FILE__
+
 /**
  * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @cfg: The timer TCFG1 register bits shifted down to 0.
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
  *
  * Return true if the given configuration from TCFG1 is a TCLK instead
  * any of the TDIV clocks.
  */
 static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
 {
-	return tcfg == S3C2410_TCFG1_MUX_TCLK;
+	return 0;
 }
 
 /**
@@ -35,7 +41,7 @@
  */
 static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
 {
-	return 1 << (1 + tcfg1);
+	return 1 << tcfg1;
 }
 
 /**
@@ -45,7 +51,7 @@
  */
 static inline unsigned int pwm_tdiv_has_div1(void)
 {
-	return 0;
+	return 1;
 }
 
 /**
@@ -56,7 +62,9 @@
  */
 static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
 {
-	return ilog2(div) - 1;
+	return ilog2(div);
 }
 
-#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
+#define S3C_TCFG1_MUX_TCLK 0
+
+#endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-s5p6442/cpu.c b/arch/arm/mach-s5p6442/cpu.c
index bc2524d..a48fb553 100644
--- a/arch/arm/mach-s5p6442/cpu.c
+++ b/arch/arm/mach-s5p6442/cpu.c
@@ -95,7 +95,7 @@
 	s5p_init_irq(vic, ARRAY_SIZE(vic));
 }
 
-static struct sysdev_class s5p6442_sysclass = {
+struct sysdev_class s5p6442_sysclass = {
 	.name	= "s5p6442-core",
 };
 
diff --git a/arch/arm/mach-s5p6442/include/mach/pwm-clock.h b/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
index 15e8525..2724b37 100644
--- a/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
+++ b/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
@@ -1,13 +1,14 @@
 /* linux/arch/arm/mach-s5p6442/include/mach/pwm-clock.h
  *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *      Ben Dooks <ben@simtec.co.uk>
  *      http://armlinux.simtec.co.uk/
  *
- * Copyright 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
+ * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
  *
  * S5P6442 - pwm clock and timer support
  *
@@ -21,14 +22,14 @@
 
 /**
  * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @cfg: The timer TCFG1 register bits shifted down to 0.
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
  *
  * Return true if the given configuration from TCFG1 is a TCLK instead
  * any of the TDIV clocks.
  */
 static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
 {
-	return tcfg == S3C2410_TCFG1_MUX_TCLK;
+	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
 }
 
 /**
@@ -40,7 +41,7 @@
  */
 static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
 {
-	return 1 << (1 + tcfg1);
+	return 1 << tcfg1;
 }
 
 /**
@@ -50,7 +51,7 @@
  */
 static inline unsigned int pwm_tdiv_has_div1(void)
 {
-	return 0;
+	return 1;
 }
 
 /**
@@ -61,9 +62,9 @@
  */
 static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
 {
-	return ilog2(div) - 1;
+	return ilog2(div);
 }
 
-#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
+#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
 
 #endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 8ebf51c..0acbdb3 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -12,7 +12,7 @@
 
 # Core support for S5PV210 system
 
-obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o
+obj-$(CONFIG_CPU_S5PV210)	+= cpu.o init.o clock.o gpiolib.o
 
 # machine support
 
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index ccccae2..154bca4 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -31,247 +31,6 @@
 #include <plat/clock-clksrc.h>
 #include <plat/s5pv210.h>
 
-static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
-}
-
-static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
-}
-
-static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
-}
-
-static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
-}
-
-static struct clk clk_h200 = {
-	.name		= "hclk200",
-	.id		= -1,
-};
-
-static struct clk clk_h100 = {
-	.name		= "hclk100",
-	.id		= -1,
-};
-
-static struct clk clk_h166 = {
-	.name		= "hclk166",
-	.id		= -1,
-};
-
-static struct clk clk_h133 = {
-	.name		= "hclk133",
-	.id		= -1,
-};
-
-static struct clk clk_p100 = {
-	.name		= "pclk100",
-	.id		= -1,
-};
-
-static struct clk clk_p83 = {
-	.name		= "pclk83",
-	.id		= -1,
-};
-
-static struct clk clk_p66 = {
-	.name		= "pclk66",
-	.id		= -1,
-};
-
-static struct clk *sys_clks[] = {
-	&clk_h200,
-	&clk_h100,
-	&clk_h166,
-	&clk_h133,
-	&clk_p100,
-	&clk_p83,
-	&clk_p66
-};
-
-static struct clk init_clocks_disable[] = {
-	{
-		.name		= "rot",
-		.id		= -1,
-		.parent		= &clk_h166,
-		.enable		= s5pv210_clk_ip0_ctrl,
-		.ctrlbit	= (1<<29),
-	}, {
-		.name		= "otg",
-		.id		= -1,
-		.parent		= &clk_h133,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<16),
-	}, {
-		.name		= "usb-host",
-		.id		= -1,
-		.parent		= &clk_h133,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<17),
-	}, {
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_h166,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<0),
-	}, {
-		.name		= "cfcon",
-		.id		= 0,
-		.parent		= &clk_h133,
-		.enable		= s5pv210_clk_ip1_ctrl,
-		.ctrlbit	= (1<<25),
-	}, {
-		.name		= "hsmmc",
-		.id		= 0,
-		.parent		= &clk_h133,
-		.enable		= s5pv210_clk_ip2_ctrl,
-		.ctrlbit	= (1<<16),
-	}, {
-		.name		= "hsmmc",
-		.id		= 1,
-		.parent		= &clk_h133,
-		.enable		= s5pv210_clk_ip2_ctrl,
-		.ctrlbit	= (1<<17),
-	}, {
-		.name		= "hsmmc",
-		.id		= 2,
-		.parent		= &clk_h133,
-		.enable		= s5pv210_clk_ip2_ctrl,
-		.ctrlbit	= (1<<18),
-	}, {
-		.name		= "hsmmc",
-		.id		= 3,
-		.parent		= &clk_h133,
-		.enable		= s5pv210_clk_ip2_ctrl,
-		.ctrlbit	= (1<<19),
-	}, {
-		.name		= "systimer",
-		.id		= -1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<16),
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<22),
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<15),
-	}, {
-		.name		= "i2c",
-		.id		= 0,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<7),
-	}, {
-		.name		= "i2c",
-		.id		= 1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<8),
-	}, {
-		.name		= "i2c",
-		.id		= 2,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<9),
-	}, {
-		.name		= "spi",
-		.id		= 0,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<12),
-	}, {
-		.name		= "spi",
-		.id		= 1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<13),
-	}, {
-		.name		= "spi",
-		.id		= 2,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<14),
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<23),
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "keypad",
-		.id		= -1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<21),
-	}, {
-		.name		= "i2s_v50",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<4),
-	}, {
-		.name		= "i2s_v32",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<4),
-	}, {
-		.name		= "i2s_v32",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<4),
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<7),
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<8),
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<9),
-	}, {
-		.name		= "uart",
-		.id		= 3,
-		.parent		= &clk_p66,
-		.enable		= s5pv210_clk_ip3_ctrl,
-		.ctrlbit	= (1<<10),
-	},
-};
-
 static struct clksrc_clk clk_mout_apll = {
 	.clk	= {
 		.name		= "mout_apll",
@@ -299,6 +58,399 @@
 	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },
 };
 
+static struct clk *clkset_armclk_list[] = {
+	[0] = &clk_mout_apll.clk,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_armclk = {
+	.sources	= clkset_armclk_list,
+	.nr_sources	= ARRAY_SIZE(clkset_armclk_list),
+};
+
+static struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name		= "armclk",
+		.id		= -1,
+	},
+	.sources	= &clkset_armclk,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },
+	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_hclk_msys = {
+	.clk	= {
+		.name		= "hclk_msys",
+		.id		= -1,
+		.parent		= &clk_armclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_pclk_msys = {
+	.clk	= {
+		.name		= "pclk_msys",
+		.id		= -1,
+		.parent		= &clk_hclk_msys.clk,
+	},
+	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_sclk_a2m = {
+	.clk	= {
+		.name		= "sclk_a2m",
+		.id		= -1,
+		.parent		= &clk_mout_apll.clk,
+	},
+	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },
+};
+
+static struct clk *clkset_hclk_sys_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_a2m.clk,
+};
+
+static struct clksrc_sources clkset_hclk_sys = {
+	.sources	= clkset_hclk_sys_list,
+	.nr_sources	= ARRAY_SIZE(clkset_hclk_sys_list),
+};
+
+static struct clksrc_clk clk_hclk_dsys = {
+	.clk	= {
+		.name	= "hclk_dsys",
+		.id	= -1,
+	},
+	.sources	= &clkset_hclk_sys,
+	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },
+	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_dsys = {
+	.clk	= {
+		.name	= "pclk_dsys",
+		.id	= -1,
+		.parent	= &clk_hclk_dsys.clk,
+	},
+	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },
+};
+
+static struct clksrc_clk clk_hclk_psys = {
+	.clk	= {
+		.name	= "hclk_psys",
+		.id	= -1,
+	},
+	.sources	= &clkset_hclk_sys,
+	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },
+	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },
+};
+
+static struct clksrc_clk clk_pclk_psys = {
+	.clk	= {
+		.name	= "pclk_psys",
+		.id	= -1,
+		.parent	= &clk_hclk_psys.clk,
+	},
+	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },
+};
+
+static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);
+}
+
+static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);
+}
+
+static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);
+}
+
+static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);
+}
+
+static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable);
+}
+
+static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);
+}
+
+static struct clk clk_sclk_hdmi27m = {
+	.name		= "sclk_hdmi27m",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+static struct clk clk_sclk_hdmiphy = {
+	.name		= "sclk_hdmiphy",
+	.id		= -1,
+};
+
+static struct clk clk_sclk_usbphy0 = {
+	.name		= "sclk_usbphy0",
+	.id		= -1,
+};
+
+static struct clk clk_sclk_usbphy1 = {
+	.name		= "sclk_usbphy1",
+	.id		= -1,
+};
+
+static struct clk clk_pcmcdclk0 = {
+	.name		= "pcmcdclk",
+	.id		= -1,
+};
+
+static struct clk clk_pcmcdclk1 = {
+	.name		= "pcmcdclk",
+	.id		= -1,
+};
+
+static struct clk clk_pcmcdclk2 = {
+	.name		= "pcmcdclk",
+	.id		= -1,
+};
+
+static struct clk *clkset_vpllsrc_list[] = {
+	[0] = &clk_fin_vpll,
+	[1] = &clk_sclk_hdmi27m,
+};
+
+static struct clksrc_sources clkset_vpllsrc = {
+	.sources	= clkset_vpllsrc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
+};
+
+static struct clksrc_clk clk_vpllsrc = {
+	.clk	= {
+		.name		= "vpll_src",
+		.id		= -1,
+		.enable		= s5pv210_clk_mask0_ctrl,
+		.ctrlbit	= (1 << 7),
+	},
+	.sources	= &clkset_vpllsrc,
+	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 },
+};
+
+static struct clk *clkset_sclk_vpll_list[] = {
+	[0] = &clk_vpllsrc.clk,
+	[1] = &clk_fout_vpll,
+};
+
+static struct clksrc_sources clkset_sclk_vpll = {
+	.sources	= clkset_sclk_vpll_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
+};
+
+static struct clksrc_clk clk_sclk_vpll = {
+	.clk	= {
+		.name		= "sclk_vpll",
+		.id		= -1,
+	},
+	.sources	= &clkset_sclk_vpll,
+	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },
+};
+
+static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk)
+{
+	return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk_ops clk_hclk_imem_ops = {
+	.get_rate	= s5pv210_clk_imem_get_rate,
+};
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "rot",
+		.id		= -1,
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip0_ctrl,
+		.ctrlbit	= (1<<29),
+	}, {
+		.name		= "otg",
+		.id		= -1,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<16),
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<17),
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_hclk_dsys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<0),
+	}, {
+		.name		= "cfcon",
+		.id		= 0,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1<<25),
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<16),
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<17),
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<18),
+	}, {
+		.name		= "hsmmc",
+		.id		= 3,
+		.parent		= &clk_hclk_psys.clk,
+		.enable		= s5pv210_clk_ip2_ctrl,
+		.ctrlbit	= (1<<19),
+	}, {
+		.name		= "systimer",
+		.id		= -1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<16),
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<22),
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<15),
+	}, {
+		.name		= "i2c",
+		.id		= 0,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<7),
+	}, {
+		.name		= "i2c",
+		.id		= 1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<8),
+	}, {
+		.name		= "i2c",
+		.id		= 2,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<9),
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<12),
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<13),
+	}, {
+		.name		= "spi",
+		.id		= 2,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<14),
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<23),
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<24),
+	}, {
+		.name		= "keypad",
+		.id		= -1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<21),
+	}, {
+		.name		= "i2s_v50",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<4),
+	}, {
+		.name		= "i2s_v32",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<4),
+	}, {
+		.name		= "i2s_v32",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<4),
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "hclk_imem",
+		.id		= -1,
+		.parent		= &clk_hclk_msys.clk,
+		.ctrlbit	= (1 << 5),
+		.enable		= s5pv210_clk_ip0_ctrl,
+		.ops		= &clk_hclk_imem_ops,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<7),
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<8),
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<9),
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.parent		= &clk_pclk_psys.clk,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1<<10),
+	},
+};
+
 static struct clk *clkset_uart_list[] = {
 	[6] = &clk_mout_mpll.clk,
 	[7] = &clk_mout_epll.clk,
@@ -309,43 +461,494 @@
 	.nr_sources	= ARRAY_SIZE(clkset_uart_list),
 };
 
+static struct clk *clkset_group1_list[] = {
+	[0] = &clk_sclk_a2m.clk,
+	[1] = &clk_mout_mpll.clk,
+	[2] = &clk_mout_epll.clk,
+	[3] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_group1 = {
+	.sources	= clkset_group1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group1_list),
+};
+
+static struct clk *clkset_sclk_onenand_list[] = {
+	[0] = &clk_hclk_psys.clk,
+	[1] = &clk_hclk_dsys.clk,
+};
+
+static struct clksrc_sources clkset_sclk_onenand = {
+	.sources	= clkset_sclk_onenand_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_onenand_list),
+};
+
+static struct clk *clkset_sclk_dac_list[] = {
+	[0] = &clk_sclk_vpll.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_dac = {
+	.sources	= clkset_sclk_dac_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_dac_list),
+};
+
+static struct clksrc_clk clk_sclk_dac = {
+	.clk		= {
+		.name		= "sclk_dac",
+		.id		= -1,
+		.ctrlbit	= (1 << 10),
+		.enable		= s5pv210_clk_ip1_ctrl,
+	},
+	.sources	= &clkset_sclk_dac,
+	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 8, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_pixel = {
+	.clk		= {
+		.name		= "sclk_pixel",
+		.id		= -1,
+		.parent		= &clk_sclk_vpll.clk,
+	},
+	.reg_div	= { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4},
+};
+
+static struct clk *clkset_sclk_hdmi_list[] = {
+	[0] = &clk_sclk_pixel.clk,
+	[1] = &clk_sclk_hdmiphy,
+};
+
+static struct clksrc_sources clkset_sclk_hdmi = {
+	.sources	= clkset_sclk_hdmi_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_hdmi_list),
+};
+
+static struct clksrc_clk clk_sclk_hdmi = {
+	.clk		= {
+		.name		= "sclk_hdmi",
+		.id		= -1,
+		.enable		= s5pv210_clk_ip1_ctrl,
+		.ctrlbit	= (1 << 11),
+	},
+	.sources	= &clkset_sclk_hdmi,
+	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_mixer_list[] = {
+	[0] = &clk_sclk_dac.clk,
+	[1] = &clk_sclk_hdmi.clk,
+};
+
+static struct clksrc_sources clkset_sclk_mixer = {
+	.sources	= clkset_sclk_mixer_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_mixer_list),
+};
+
+static struct clk *clkset_sclk_audio0_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_pcmcdclk0,
+	[2] = &clk_sclk_hdmi27m,
+	[3] = &clk_sclk_usbphy0,
+	[4] = &clk_sclk_usbphy1,
+	[5] = &clk_sclk_hdmiphy,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_sclk_audio0 = {
+	.sources	= clkset_sclk_audio0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio0_list),
+};
+
+static struct clksrc_clk clk_sclk_audio0 = {
+	.clk		= {
+		.name		= "sclk_audio",
+		.id		= 0,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1 << 4),
+	},
+	.sources = &clkset_sclk_audio0,
+	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 0, .size = 4 },
+	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 },
+};
+
+static struct clk *clkset_sclk_audio1_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_pcmcdclk1,
+	[2] = &clk_sclk_hdmi27m,
+	[3] = &clk_sclk_usbphy0,
+	[4] = &clk_sclk_usbphy1,
+	[5] = &clk_sclk_hdmiphy,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_sclk_audio1 = {
+	.sources	= clkset_sclk_audio1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio1_list),
+};
+
+static struct clksrc_clk clk_sclk_audio1 = {
+	.clk		= {
+		.name		= "sclk_audio",
+		.id		= 1,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1 << 5),
+	},
+	.sources = &clkset_sclk_audio1,
+	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 4, .size = 4 },
+	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 4, .size = 4 },
+};
+
+static struct clk *clkset_sclk_audio2_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_pcmcdclk0,
+	[2] = &clk_sclk_hdmi27m,
+	[3] = &clk_sclk_usbphy0,
+	[4] = &clk_sclk_usbphy1,
+	[5] = &clk_sclk_hdmiphy,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_sclk_audio2 = {
+	.sources	= clkset_sclk_audio2_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_audio2_list),
+};
+
+static struct clksrc_clk clk_sclk_audio2 = {
+	.clk		= {
+		.name		= "sclk_audio",
+		.id		= 2,
+		.enable		= s5pv210_clk_ip3_ctrl,
+		.ctrlbit	= (1 << 6),
+	},
+	.sources = &clkset_sclk_audio2,
+	.reg_src = { .reg = S5P_CLK_SRC6, .shift = 8, .size = 4 },
+	.reg_div = { .reg = S5P_CLK_DIV6, .shift = 8, .size = 4 },
+};
+
+static struct clk *clkset_sclk_spdif_list[] = {
+	[0] = &clk_sclk_audio0.clk,
+	[1] = &clk_sclk_audio1.clk,
+	[2] = &clk_sclk_audio2.clk,
+};
+
+static struct clksrc_sources clkset_sclk_spdif = {
+	.sources	= clkset_sclk_spdif_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_spdif_list),
+};
+
+static struct clk *clkset_group2_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_xusbxti,
+	[2] = &clk_sclk_hdmi27m,
+	[3] = &clk_sclk_usbphy0,
+	[4] = &clk_sclk_usbphy1,
+	[5] = &clk_sclk_hdmiphy,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_group2 = {
+	.sources	= clkset_group2_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group2_list),
+};
+
 static struct clksrc_clk clksrcs[] = {
 	{
 		.clk	= {
-			.name		= "uclk1",
+			.name		= "sclk_dmc",
 			.id		= -1,
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_onenand",
+			.id		= -1,
+		},
+		.sources = &clkset_sclk_onenand,
+		.reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 },
+		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 },
+	}, {
+		.clk	= {
+			.name		= "uclk1",
+			.id		= 0,
 			.ctrlbit	= (1<<17),
 			.enable		= s5pv210_clk_ip3_ctrl,
 		},
 		.sources = &clkset_uart,
 		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 },
 		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 },
-	}
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 1,
+			.enable		= s5pv210_clk_ip3_ctrl,
+			.ctrlbit	= (1 << 18),
+		},
+		.sources = &clkset_uart,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 2,
+			.enable		= s5pv210_clk_ip3_ctrl,
+			.ctrlbit	= (1 << 19),
+		},
+		.sources = &clkset_uart,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 3,
+			.enable		= s5pv210_clk_ip3_ctrl,
+			.ctrlbit	= (1 << 20),
+		},
+		.sources = &clkset_uart,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_mixer",
+			.id		= -1,
+			.enable		= s5pv210_clk_ip1_ctrl,
+			.ctrlbit	= (1 << 9),
+		},
+		.sources = &clkset_sclk_mixer,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spdif",
+			.id		= -1,
+			.enable		= s5pv210_clk_mask0_ctrl,
+			.ctrlbit	= (1 << 27),
+		},
+		.sources = &clkset_sclk_spdif,
+		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 },
+	}, {
+		.clk	= {
+			.name		= "sclk_fimc",
+			.id		= 0,
+			.enable		= s5pv210_clk_ip0_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_fimc",
+			.id		= 1,
+			.enable		= s5pv210_clk_ip0_ctrl,
+			.ctrlbit	= (1 << 25),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 },
+	}, {
+		.clk	= {
+			.name		= "sclk_fimc",
+			.id		= 2,
+			.enable		= s5pv210_clk_ip0_ctrl,
+			.ctrlbit	= (1 << 26),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam",
+			.id		= 0,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam",
+			.id		= 1,
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.id		= -1,
+			.enable		= s5pv210_clk_ip1_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 0,
+			.enable		= s5pv210_clk_ip2_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 1,
+			.enable		= s5pv210_clk_ip2_ctrl,
+			.ctrlbit	= (1 << 17),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 2,
+			.enable		= s5pv210_clk_ip2_ctrl,
+			.ctrlbit	= (1 << 18),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 3,
+			.enable		= s5pv210_clk_ip2_ctrl,
+			.ctrlbit	= (1 << 19),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mfc",
+			.id		= -1,
+			.enable		= s5pv210_clk_ip0_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_g2d",
+			.id		= -1,
+			.enable		= s5pv210_clk_ip0_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_g3d",
+			.id		= -1,
+			.enable		= s5pv210_clk_ip0_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.sources = &clkset_group1,
+		.reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 },
+		.reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_csis",
+			.id		= -1,
+			.enable		= s5pv210_clk_ip0_ctrl,
+			.ctrlbit	= (1 << 31),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 0,
+			.enable		= s5pv210_clk_ip3_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 1,
+			.enable		= s5pv210_clk_ip3_ctrl,
+			.ctrlbit	= (1 << 13),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_pwi",
+			.id		= -1,
+			.enable		= &s5pv210_clk_ip4_ctrl,
+			.ctrlbit	= (1 << 2),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC6, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV6, .shift = 24, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_pwm",
+			.id		= -1,
+			.enable		= s5pv210_clk_ip3_ctrl,
+			.ctrlbit	= (1 << 23),
+		},
+		.sources = &clkset_group2,
+		.reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 },
+	},
 };
 
 /* Clock initialisation code */
-static struct clksrc_clk *init_parents[] = {
+static struct clksrc_clk *sysclks[] = {
 	&clk_mout_apll,
 	&clk_mout_epll,
 	&clk_mout_mpll,
+	&clk_armclk,
+	&clk_hclk_msys,
+	&clk_sclk_a2m,
+	&clk_hclk_dsys,
+	&clk_hclk_psys,
+	&clk_pclk_msys,
+	&clk_pclk_dsys,
+	&clk_pclk_psys,
+	&clk_vpllsrc,
+	&clk_sclk_vpll,
+	&clk_sclk_dac,
+	&clk_sclk_pixel,
+	&clk_sclk_hdmi,
 };
 
-#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
-
 void __init_or_cpufreq s5pv210_setup_clocks(void)
 {
 	struct clk *xtal_clk;
 	unsigned long xtal;
+	unsigned long vpllsrc;
 	unsigned long armclk;
-	unsigned long hclk200;
-	unsigned long hclk166;
-	unsigned long hclk133;
-	unsigned long pclk100;
-	unsigned long pclk83;
-	unsigned long pclk66;
+	unsigned long hclk_msys;
+	unsigned long hclk_dsys;
+	unsigned long hclk_psys;
+	unsigned long pclk_msys;
+	unsigned long pclk_dsys;
+	unsigned long pclk_psys;
 	unsigned long apll;
 	unsigned long mpll;
 	unsigned long epll;
+	unsigned long vpll;
 	unsigned int ptr;
 	u32 clkdiv0, clkdiv1;
 
@@ -368,59 +971,46 @@
 	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);
 	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502);
 	epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500);
-
-	printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld",
-			apll, mpll, epll);
-
-	armclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_APLL);
-	if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX200_MASK)
-		hclk200 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
-	else
-		hclk200 = armclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200);
-
-	if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX166_MASK) {
-		hclk166 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
-		hclk166 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
-	} else
-		hclk166 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166);
-
-	if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX133_MASK) {
-		hclk133 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M);
-		hclk133 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
-	} else
-		hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133);
-
-	pclk100 = hclk200 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100);
-	pclk83 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83);
-	pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66);
-
-	printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \
-			HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
-	       armclk, hclk200, hclk166, hclk133, pclk100, pclk83, pclk66);
+	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+	vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502);
 
 	clk_fout_apll.rate = apll;
 	clk_fout_mpll.rate = mpll;
 	clk_fout_epll.rate = epll;
+	clk_fout_vpll.rate = vpll;
+
+	printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
+			apll, mpll, epll, vpll);
+
+	armclk = clk_get_rate(&clk_armclk.clk);
+	hclk_msys = clk_get_rate(&clk_hclk_msys.clk);
+	hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk);
+	hclk_psys = clk_get_rate(&clk_hclk_psys.clk);
+	pclk_msys = clk_get_rate(&clk_pclk_msys.clk);
+	pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk);
+	pclk_psys = clk_get_rate(&clk_pclk_psys.clk);
+
+	printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n"
+			 "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n",
+			armclk, hclk_msys, hclk_dsys, hclk_psys,
+			pclk_msys, pclk_dsys, pclk_psys);
 
 	clk_f.rate = armclk;
-	clk_h.rate = hclk133;
-	clk_p.rate = pclk66;
-	clk_p66.rate = pclk66;
-	clk_p83.rate = pclk83;
-	clk_h133.rate = hclk133;
-	clk_h166.rate = hclk166;
-	clk_h200.rate = hclk200;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++)
-		s3c_set_clksrc(init_parents[ptr], true);
+	clk_h.rate = hclk_psys;
+	clk_p.rate = pclk_psys;
 
 	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
 		s3c_set_clksrc(&clksrcs[ptr], true);
 }
 
 static struct clk *clks[] __initdata = {
-	&clk_mout_epll.clk,
-	&clk_mout_mpll.clk,
+	&clk_sclk_hdmi27m,
+	&clk_sclk_hdmiphy,
+	&clk_sclk_usbphy0,
+	&clk_sclk_usbphy1,
+	&clk_pcmcdclk0,
+	&clk_pcmcdclk1,
+	&clk_pcmcdclk2,
 };
 
 void __init s5pv210_register_clocks(void)
@@ -433,13 +1023,12 @@
 	if (ret > 0)
 		printk(KERN_ERR "Failed to register %u clocks\n", ret);
 
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
 	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
 	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
 
-	ret = s3c24xx_register_clocks(sys_clks, ARRAY_SIZE(sys_clks));
-	if (ret > 0)
-		printk(KERN_ERR "Failed to register system clocks\n");
-
 	clkp = init_clocks_disable;
 	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
 		ret = s3c24xx_register_clock(clkp);
diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c
index 0e0f8fd..2b776eb 100644
--- a/arch/arm/mach-s5pv210/cpu.c
+++ b/arch/arm/mach-s5pv210/cpu.c
@@ -100,7 +100,7 @@
 	s5p_init_irq(vic, ARRAY_SIZE(vic));
 }
 
-static struct sysdev_class s5pv210_sysclass = {
+struct sysdev_class s5pv210_sysclass = {
 	.name	= "s5pv210-core",
 };
 
diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c
new file mode 100644
index 0000000..9ea8972
--- /dev/null
+++ b/arch/arm/mach-s5pv210/gpiolib.c
@@ -0,0 +1,261 @@
+/* linux/arch/arm/mach-s5pv210/gpiolib.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5PV210 - GPIOlib support
+ *
+ * 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/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <mach/map.h>
+
+static struct s3c_gpio_cfg gpio_cfg = {
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_cfg_noint = {
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+/* GPIO bank's base address given the index of the bank in the
+ * list of all gpio banks.
+ */
+#define S5PV210_BANK_BASE(bank_nr)	(S5P_VA_GPIO + ((bank_nr) * 0x20))
+
+/*
+ * Following are the gpio banks in v210.
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure gpio_cfg in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of s3c_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
+	{
+		.chip	= {
+			.base	= S5PV210_GPA0(0),
+			.ngpio	= S5PV210_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPA1(0),
+			.ngpio	= S5PV210_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPB(0),
+			.ngpio	= S5PV210_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPC0(0),
+			.ngpio	= S5PV210_GPIO_C0_NR,
+			.label	= "GPC0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPC1(0),
+			.ngpio	= S5PV210_GPIO_C1_NR,
+			.label	= "GPC1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPD0(0),
+			.ngpio	= S5PV210_GPIO_D0_NR,
+			.label	= "GPD0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPD1(0),
+			.ngpio	= S5PV210_GPIO_D1_NR,
+			.label	= "GPD1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPE0(0),
+			.ngpio	= S5PV210_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPE1(0),
+			.ngpio	= S5PV210_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF0(0),
+			.ngpio	= S5PV210_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF1(0),
+			.ngpio	= S5PV210_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF2(0),
+			.ngpio	= S5PV210_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPF3(0),
+			.ngpio	= S5PV210_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG0(0),
+			.ngpio	= S5PV210_GPIO_G0_NR,
+			.label	= "GPG0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG1(0),
+			.ngpio	= S5PV210_GPIO_G1_NR,
+			.label	= "GPG1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG2(0),
+			.ngpio	= S5PV210_GPIO_G2_NR,
+			.label	= "GPG2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPG3(0),
+			.ngpio	= S5PV210_GPIO_G3_NR,
+			.label	= "GPG3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPI(0),
+			.ngpio	= S5PV210_GPIO_I_NR,
+			.label	= "GPI",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ0(0),
+			.ngpio	= S5PV210_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ1(0),
+			.ngpio	= S5PV210_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ2(0),
+			.ngpio	= S5PV210_GPIO_J2_NR,
+			.label	= "GPJ2",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ3(0),
+			.ngpio	= S5PV210_GPIO_J3_NR,
+			.label	= "GPJ3",
+		},
+	}, {
+		.chip	= {
+			.base	= S5PV210_GPJ4(0),
+			.ngpio	= S5PV210_GPIO_J4_NR,
+			.label	= "GPJ4",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV210_MP01(0),
+			.ngpio	= S5PV210_GPIO_MP01_NR,
+			.label	= "MP01",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV210_MP02(0),
+			.ngpio	= S5PV210_GPIO_MP02_NR,
+			.label	= "MP02",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV210_MP03(0),
+			.ngpio	= S5PV210_GPIO_MP03_NR,
+			.label	= "MP03",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC00),
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV210_GPH0(0),
+			.ngpio	= S5PV210_GPIO_H0_NR,
+			.label	= "GPH0",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC20),
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV210_GPH1(0),
+			.ngpio	= S5PV210_GPIO_H1_NR,
+			.label	= "GPH1",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC40),
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV210_GPH2(0),
+			.ngpio	= S5PV210_GPIO_H2_NR,
+			.label	= "GPH2",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO + 0xC60),
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= S5PV210_GPH3(0),
+			.ngpio	= S5PV210_GPIO_H3_NR,
+			.label	= "GPH3",
+		},
+	},
+};
+
+static __init int s5pv210_gpiolib_init(void)
+{
+	struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
+	int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
+	int i = 0;
+
+	for (i = 0; i < nr_chips; i++, chip++) {
+		if (chip->config == NULL)
+			chip->config = &gpio_cfg;
+		if (chip->base == NULL)
+			chip->base = S5PV210_BANK_BASE(i);
+	}
+
+	samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
+
+	return 0;
+}
+core_initcall(s5pv210_gpiolib_init);
diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h
index 533b020..d6461ba 100644
--- a/arch/arm/mach-s5pv210/include/mach/gpio.h
+++ b/arch/arm/mach-s5pv210/include/mach/gpio.h
@@ -18,6 +18,8 @@
 #define gpio_cansleep	__gpio_cansleep
 #define gpio_to_irq	__gpio_to_irq
 
+/* Practically, GPIO banks upto MP03 are the configurable gpio banks */
+
 /* GPIO bank sizes */
 #define S5PV210_GPIO_A0_NR	(8)
 #define S5PV210_GPIO_A1_NR	(4)
@@ -47,6 +49,10 @@
 #define S5PV210_GPIO_J3_NR	(8)
 #define S5PV210_GPIO_J4_NR	(5)
 
+#define S5PV210_GPIO_MP01_NR	(8)
+#define S5PV210_GPIO_MP02_NR	(4)
+#define S5PV210_GPIO_MP03_NR	(8)
+
 /* GPIO bank numbers */
 
 /* CONFIG_S3C_GPIO_SPACE allows the user to select extra
@@ -85,6 +91,9 @@
 	S5PV210_GPIO_J2_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J1),
 	S5PV210_GPIO_J3_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J2),
 	S5PV210_GPIO_J4_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J3),
+	S5PV210_GPIO_MP01_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_J4),
+	S5PV210_GPIO_MP02_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_MP01),
+	S5PV210_GPIO_MP03_START	= S5PV210_GPIO_NEXT(S5PV210_GPIO_MP02),
 };
 
 /* S5PV210 GPIO number definitions */
@@ -115,13 +124,16 @@
 #define S5PV210_GPJ2(_nr)	(S5PV210_GPIO_J2_START + (_nr))
 #define S5PV210_GPJ3(_nr)	(S5PV210_GPIO_J3_START + (_nr))
 #define S5PV210_GPJ4(_nr)	(S5PV210_GPIO_J4_START + (_nr))
+#define S5PV210_MP01(_nr)	(S5PV210_GPIO_MP01_START + (_nr))
+#define S5PV210_MP02(_nr)	(S5PV210_GPIO_MP02_START + (_nr))
+#define S5PV210_MP03(_nr)	(S5PV210_GPIO_MP03_START + (_nr))
 
 /* the end of the S5PV210 specific gpios */
-#define S5PV210_GPIO_END	(S5PV210_GPJ4(S5PV210_GPIO_J4_NR) + 1)
+#define S5PV210_GPIO_END	(S5PV210_MP03(S5PV210_GPIO_MP03_NR) + 1)
 #define S3C_GPIO_END		S5PV210_GPIO_END
 
-/* define the number of gpios we need to the one after the GPJ4() range */
-#define ARCH_NR_GPIOS		(S5PV210_GPJ4(S5PV210_GPIO_J4_NR) +	\
+/* define the number of gpios we need to the one after the MP03() range */
+#define ARCH_NR_GPIOS		(S5PV210_MP03(S5PV210_GPIO_MP03_NR) +	\
 				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
 
 #include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-s5pv210/include/mach/pwm-clock.h b/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
index 69027fe..f8a9f1b 100644
--- a/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
@@ -1,13 +1,14 @@
 /* linux/arch/arm/mach-s5pv210/include/mach/pwm-clock.h
  *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
  *      Ben Dooks <ben@simtec.co.uk>
  *      http://armlinux.simtec.co.uk/
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h
+ * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
  *
  * S5PV210 - pwm clock and timer support
  *
@@ -21,14 +22,14 @@
 
 /**
  * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @cfg: The timer TCFG1 register bits shifted down to 0.
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
  *
  * Return true if the given configuration from TCFG1 is a TCLK instead
  * any of the TDIV clocks.
  */
 static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
 {
-	return tcfg == S3C2410_TCFG1_MUX_TCLK;
+	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
 }
 
 /**
@@ -40,7 +41,7 @@
  */
 static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
 {
-	return 1 << (1 + tcfg1);
+	return 1 << tcfg1;
 }
 
 /**
@@ -50,7 +51,7 @@
  */
 static inline unsigned int pwm_tdiv_has_div1(void)
 {
-	return 0;
+	return 1;
 }
 
 /**
@@ -61,9 +62,9 @@
  */
 static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
 {
-	return ilog2(div) - 1;
+	return ilog2(div);
 }
 
-#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK
+#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
 
 #endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 241c24a..45a1bc2 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -869,9 +869,10 @@
 	if (machine_is_p720t())
 		res_size = 0x00014000;
 
-	/* H1940 and RX3715 need to reserve this for suspend */
+	/* H1940, RX3715 and RX1950 need to reserve this for suspend */
 
-	if (machine_is_h1940() || machine_is_rx3715()) {
+	if (machine_is_h1940() || machine_is_rx3715()
+		|| machine_is_rx1950()) {
 		reserve_bootmem_node(pgdat, 0x30003000, 0x1000,
 				BOOTMEM_DEFAULT);
 		reserve_bootmem_node(pgdat, 0x30081000, 0x1000,
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 9265f09..cd5b41d 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -149,10 +150,14 @@
 {
 	struct s3c2410fb_mach_info *npd;
 
-	npd = kmalloc(sizeof(*npd), GFP_KERNEL);
+	npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL);
 	if (npd) {
-		memcpy(npd, pd, sizeof(*npd));
 		s3c_device_lcd.dev.platform_data = npd;
+		npd->displays = kmemdup(pd->displays,
+			sizeof(struct s3c2410fb_display) * npd->num_displays,
+			GFP_KERNEL);
+		if (!npd->displays)
+			printk(KERN_ERR "no memory for LCD display data\n");
 	} else {
 		printk(KERN_ERR "no memory for LCD platform data\n");
 	}
@@ -338,14 +343,6 @@
 	.resource	  = s3c_adc_resource,
 };
 
-/* HWMON */
-
-struct platform_device s3c_device_hwmon = {
-	.name		= "s3c-hwmon",
-	.id		= -1,
-	.dev.parent	= &s3c_device_adc.dev,
-};
-
 /* SDI */
 
 static struct resource s3c_sdi_resource[] = {
@@ -371,7 +368,7 @@
 
 EXPORT_SYMBOL(s3c_device_sdi);
 
-void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
+void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata)
 {
 	struct s3c24xx_mci_pdata *npd;
 
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 93827b3..6ad274e 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1104,7 +1104,7 @@
  * devaddr:   physical address of the source
 */
 
-int s3c2410_dma_devconfig(int channel,
+int s3c2410_dma_devconfig(unsigned int channel,
 			  enum s3c2410_dmasrc source,
 			  unsigned long devaddr)
 {
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
index 45126d3..2f3d7c0 100644
--- a/arch/arm/plat-s3c24xx/gpio.c
+++ b/arch/arm/plat-s3c24xx/gpio.c
@@ -34,6 +34,8 @@
 
 #include <mach/regs-gpio.h>
 
+#include <plat/gpio-core.h>
+
 /* gpiolib wrappers until these are totally eliminated */
 
 void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
@@ -68,10 +70,10 @@
 
 unsigned int s3c2410_gpio_getpin(unsigned int pin)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	unsigned long offs = pin - chip->chip.base;
 
-	return __raw_readl(base + 0x04) & (1<< offs);
+	return __raw_readl(chip->base + 0x04) & (1<< offs);
 }
 
 EXPORT_SYMBOL(s3c2410_gpio_getpin);
diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c
index aa96e33..a8bfabf4 100644
--- a/arch/arm/plat-s5p/clock.c
+++ b/arch/arm/plat-s5p/clock.c
@@ -33,6 +33,11 @@
 	.id		= -1,
 };
 
+struct clk clk_xusbxti = {
+	.name		= "xusbxti",
+	.id		= -1,
+};
+
 static struct clk s5p_clk_27m = {
 	.name		= "clk_27m",
 	.id		= -1,
@@ -69,6 +74,13 @@
 	.ctrlbit	= (1 << 31),
 };
 
+/* VPLL clock output */
+struct clk clk_fout_vpll = {
+	.name		= "fout_vpll",
+	.id		= -1,
+	.ctrlbit	= (1 << 31),
+};
+
 /* ARM clock */
 struct clk clk_arm = {
 	.name		= "armclk",
@@ -133,6 +145,7 @@
 	&clk_fout_apll,
 	&clk_fout_mpll,
 	&clk_fout_epll,
+	&clk_fout_vpll,
 	&clk_arm,
 	&clk_vpll,
 };
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h
index 42e757f..9ff3d71 100644
--- a/arch/arm/plat-s5p/include/plat/irqs.h
+++ b/arch/arm/plat-s5p/include/plat/irqs.h
@@ -79,7 +79,7 @@
 #define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
 #define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
 
-#define S5P_TIMER_IRQ(x)	S5P_IRQ(11 + (x))
+#define S5P_TIMER_IRQ(x)	(11 + (x))
 
 #define IRQ_TIMER0		S5P_TIMER_IRQ(0)
 #define IRQ_TIMER1		S5P_TIMER_IRQ(1)
diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h
index 56fb8b4..aa0447a 100644
--- a/arch/arm/plat-s5p/include/plat/s5p-clock.h
+++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h
@@ -23,10 +23,12 @@
 #define clk_fin_vpll clk_ext_xtal_mux
 
 extern struct clk clk_ext_xtal_mux;
+extern struct clk clk_xusbxti;
 extern struct clk clk_48m;
 extern struct clk clk_fout_apll;
 extern struct clk clk_fout_mpll;
 extern struct clk clk_fout_epll;
+extern struct clk clk_fout_vpll;
 extern struct clk clk_arm;
 extern struct clk clk_vpll;
 
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index d552c65..7a36cf8 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -160,6 +160,11 @@
 	help
 	  Compile in platform device definitions for HSMMC channel 2
 
+config S3C_DEV_HWMON
+	bool
+	help
+	    Compile in platform device definitions for HWMON
+
 config S3C_DEV_I2C1
 	bool
 	help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 22c89d0..0ad820a 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -33,6 +33,7 @@
 obj-$(CONFIG_S3C_DEV_HSMMC)	+= dev-hsmmc.o
 obj-$(CONFIG_S3C_DEV_HSMMC1)	+= dev-hsmmc1.o
 obj-$(CONFIG_S3C_DEV_HSMMC2)	+= dev-hsmmc2.o
+obj-$(CONFIG_S3C_DEV_HWMON)	+= dev-hwmon.o
 obj-y				+= dev-i2c0.o
 obj-$(CONFIG_S3C_DEV_I2C1)	+= dev-i2c1.o
 obj-$(CONFIG_S3C_DEV_FB)	+= dev-fb.o
diff --git a/arch/arm/plat-samsung/dev-hwmon.c b/arch/arm/plat-samsung/dev-hwmon.c
new file mode 100644
index 0000000..b3ffb95
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-hwmon.c
@@ -0,0 +1,42 @@
+/* linux/arch/arm/plat-samsung/dev-hwmon.c
+ *
+ * Copyright 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *	http://armlinux.simtec.co.uk/
+ *
+ * Adapted for HWMON by Maurus Cuelenaere
+ *
+ * Samsung series device definition for HWMON
+ *
+ * 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/platform_device.h>
+
+#include <plat/devs.h>
+#include <plat/hwmon.h>
+
+struct platform_device s3c_device_hwmon = {
+	.name		= "s3c-hwmon",
+	.id		= -1,
+	.dev.parent	= &s3c_device_adc.dev,
+};
+
+void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd)
+{
+	struct s3c_hwmon_pdata *npd;
+
+	if (!pd) {
+		printk(KERN_ERR "%s: no platform data\n", __func__);
+		return;
+	}
+
+	npd = kmemdup(pd, sizeof(struct s3c_hwmon_pdata), GFP_KERNEL);
+	if (!npd)
+		printk(KERN_ERR "%s: no memory for platform data\n", __func__);
+
+	s3c_device_hwmon.dev.platform_data = npd;
+}
diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c
index 3282db3..a76eef5 100644
--- a/arch/arm/plat-samsung/gpio-config.c
+++ b/arch/arm/plat-samsung/gpio-config.c
@@ -33,9 +33,9 @@
 
 	offset = pin - chip->chip.base;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(chip, flags);
 	ret = s3c_gpio_do_setcfg(chip, offset, config);
-	local_irq_restore(flags);
+	s3c_gpio_unlock(chip, flags);
 
 	return ret;
 }
@@ -51,9 +51,9 @@
 	if (chip) {
 		offset = pin - chip->chip.base;
 
-		local_irq_save(flags);
+		s3c_gpio_lock(chip, flags);
 		ret = s3c_gpio_do_getcfg(chip, offset);
-		local_irq_restore(flags);
+		s3c_gpio_unlock(chip, flags);
 	}
 
 	return ret;
@@ -72,9 +72,9 @@
 
 	offset = pin - chip->chip.base;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(chip, flags);
 	ret = s3c_gpio_do_setpull(chip, offset, pull);
-	local_irq_restore(flags);
+	s3c_gpio_unlock(chip, flags);
 
 	return ret;
 }
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c
index 28d2ab8..b83a833 100644
--- a/arch/arm/plat-samsung/gpio.c
+++ b/arch/arm/plat-samsung/gpio.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/spinlock.h>
 
 #include <plat/gpio-core.h>
 
@@ -52,14 +53,14 @@
 	unsigned long flags;
 	unsigned long con;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(ourchip, flags);
 
 	con = __raw_readl(base + 0x00);
 	con &= ~(3 << (offset * 2));
 
 	__raw_writel(con, base + 0x00);
 
-	local_irq_restore(flags);
+	s3c_gpio_unlock(ourchip, flags);
 	return 0;
 }
 
@@ -72,7 +73,7 @@
 	unsigned long dat;
 	unsigned long con;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(ourchip, flags);
 
 	dat = __raw_readl(base + 0x04);
 	dat &= ~(1 << offset);
@@ -87,7 +88,7 @@
 	__raw_writel(con, base + 0x00);
 	__raw_writel(dat, base + 0x04);
 
-	local_irq_restore(flags);
+	s3c_gpio_unlock(ourchip, flags);
 	return 0;
 }
 
@@ -99,7 +100,7 @@
 	unsigned long flags;
 	unsigned long dat;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(ourchip, flags);
 
 	dat = __raw_readl(base + 0x04);
 	dat &= ~(1 << offset);
@@ -107,7 +108,7 @@
 		dat |= 1 << offset;
 	__raw_writel(dat, base + 0x04);
 
-	local_irq_restore(flags);
+	s3c_gpio_unlock(ourchip, flags);
 }
 
 static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
@@ -131,6 +132,8 @@
 	BUG_ON(!gc->label);
 	BUG_ON(!gc->ngpio);
 
+	spin_lock_init(&chip->lock);
+
 	if (!gc->direction_input)
 		gc->direction_input = s3c_gpiolib_input;
 	if (!gc->direction_output)
diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h
index 12caf48..0fbcd0e 100644
--- a/arch/arm/plat-samsung/include/plat/clock.h
+++ b/arch/arm/plat-samsung/include/plat/clock.h
@@ -74,6 +74,7 @@
 extern struct clk clk_h2;
 extern struct clk clk_27m;
 extern struct clk clk_48m;
+extern struct clk clk_xusbxti;
 
 extern int clk_default_setrate(struct clk *clk, unsigned long rate);
 extern struct clk_ops clk_ops_def_setrate;
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 5dbeb79..6412933 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -79,6 +79,9 @@
 extern struct sysdev_class s3c2443_sysclass;
 extern struct sysdev_class s3c6410_sysclass;
 extern struct sysdev_class s3c64xx_sysclass;
+extern struct sysdev_class s5p6440_sysclass;
+extern struct sysdev_class s5p6442_sysclass;
+extern struct sysdev_class s5pv210_sysclass;
 
 extern void (*s5pc1xx_idle)(void);
 
diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h
index 7584d75..2e8f8c6 100644
--- a/arch/arm/plat-samsung/include/plat/dma.h
+++ b/arch/arm/plat-samsung/include/plat/dma.h
@@ -110,8 +110,8 @@
  * configure the device we're talking to
 */
 
-extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
-				 unsigned long devaddr);
+extern int s3c2410_dma_devconfig(unsigned int channel,
+		enum s3c2410_dmasrc source, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
  *
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index f0584f2..f3a68d1 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -44,16 +44,26 @@
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @config: special function and pull-resistor control information.
+ * @lock: Lock for exclusive access to this gpio bank.
  * @pm_save: Save information for suspend/resume support.
  *
  * This wrapper provides the necessary information for the Samsung
  * specific gpios being registered with gpiolib.
+ *
+ * The lock protects each gpio bank from multiple access of the shared
+ * configuration registers, or from reading of data whilst another thread
+ * is writing to the register set.
+ *
+ * Each chip has its own lock to avoid any  contention between different
+ * CPU cores trying to get one lock for different GPIO banks, where each
+ * bank of GPIO has its own register space and configuration registers.
  */
 struct s3c_gpio_chip {
 	struct gpio_chip	chip;
 	struct s3c_gpio_cfg	*config;
 	struct s3c_gpio_pm	*pm;
 	void __iomem		*base;
+	spinlock_t		 lock;
 #ifdef CONFIG_PM
 	u32			pm_save[4];
 #endif
@@ -138,3 +148,7 @@
 #define __gpio_pm(x) NULL
 
 #endif /* CONFIG_PM */
+
+/* locking wrappers to deal with multiple access to the same gpio bank */
+#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
+#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)
diff --git a/arch/arm/plat-samsung/include/plat/hwmon.h b/arch/arm/plat-samsung/include/plat/hwmon.h
index 1ba88ea..c167e44 100644
--- a/arch/arm/plat-samsung/include/plat/hwmon.h
+++ b/arch/arm/plat-samsung/include/plat/hwmon.h
@@ -37,5 +37,15 @@
 	struct s3c_hwmon_chcfg	*in[8];
 };
 
+/**
+ * s3c_hwmon_set_platdata - Set platform data for S3C HWMON device
+ * @pd: Platform data to register to device.
+ *
+ * Register the given platform data for use with the S3C HWMON device.
+ * The call will copy the platform data, so the board definitions can
+ * make the structure itself __initdata.
+ */
+extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd);
+
 #endif /* __ASM_ARCH_ADC_HWMON_H */
 
diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c
index 69a4c7f..d50ab9d 100644
--- a/arch/arm/plat-samsung/pm-gpio.c
+++ b/arch/arm/plat-samsung/pm-gpio.c
@@ -329,7 +329,7 @@
 	struct s3c_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
-	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
 		ourchip = s3c_gpiolib_getchip(gpio_nr);
 		if (!ourchip)
 			continue;
@@ -367,7 +367,7 @@
 	struct s3c_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
-	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
 		ourchip = s3c_gpiolib_getchip(gpio_nr);
 		if (!ourchip)
 			continue;