[ARM] 4157/2: S3C24XX: move arch/arch/mach-s3c2410 into cpu components

The following patch and script moves the arch/arm/mach-s3c2410
directory into arch/arm/plat-s3c24xx for the generic core code
and inti arch/arm/mach-s3c{cpu} for the cpu/machine support files

Include directory include/asm-arm/plat-s3c24xx is added for the
core include files.

Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 6783c2e..51ee13e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -363,7 +363,15 @@
 
 source "arch/arm/mach-omap2/Kconfig"
 
+source "arch/arm/plat-s3c24xx/Kconfig"
+
+if ARCH_S3C2410
+source "arch/arm/mach-s3c2400/Kconfig"
 source "arch/arm/mach-s3c2410/Kconfig"
+source "arch/arm/mach-s3c2412/Kconfig"
+source "arch/arm/mach-s3c2440/Kconfig"
+source "arch/arm/mach-s3c2442/Kconfig"
+endif
 
 source "arch/arm/mach-lh7a40x/Kconfig"
 
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 000f110..2df1ea0 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -149,7 +149,7 @@
 else
 MACHINE  :=
 endif
-  
+
 export	TEXT_OFFSET GZFLAGS MMUEXT
 
 # Do we have FASTFPE?
@@ -161,6 +161,10 @@
 # If we have a machine-specific directory, then include it in the build.
 core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
 core-y				+= $(MACHINE)
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2400/
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2412/
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2440/
+core-$(CONFIG_ARCH_S3C2410)	+= arch/arm/mach-s3c2442/
 core-$(CONFIG_FPE_NWFPE)	+= arch/arm/nwfpe/
 core-$(CONFIG_FPE_FASTFPE)	+= $(FASTFPE_OBJ)
 core-$(CONFIG_VFP)		+= arch/arm/vfp/
@@ -168,6 +172,7 @@
 # If we have a common platform directory, then include it in the build.
 core-$(CONFIG_PLAT_IOP)		+= arch/arm/plat-iop/
 core-$(CONFIG_ARCH_OMAP)	+= arch/arm/plat-omap/
+core-$(CONFIG_PLAT_S3C24XX)		+= arch/arm/plat-s3c24xx/
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 drivers-$(CONFIG_ARCH_CLPS7500)	+= drivers/acorn/char/
diff --git a/arch/arm/mach-s3c2400/Kconfig b/arch/arm/mach-s3c2400/Kconfig
new file mode 100644
index 0000000..deab0722
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Kconfig
@@ -0,0 +1,13 @@
+# arch/arm/mach-s3c2400/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+
+
+menu "S3C2400 Machines"
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2400/Makefile b/arch/arm/mach-s3c2400/Makefile
new file mode 100644
index 0000000..7e23f4e
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Makefile
@@ -0,0 +1,15 @@
+# arch/arm/mach-s3c2400/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2400)	+= gpio.o
+
+# Machine support
+
diff --git a/arch/arm/mach-s3c2410/s3c2400-gpio.c b/arch/arm/mach-s3c2400/gpio.c
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2400-gpio.c
rename to arch/arm/mach-s3c2400/gpio.c
index 1576d01..758e1604 100644
--- a/arch/arm/mach-s3c2410/s3c2400-gpio.c
+++ b/arch/arm/mach-s3c2400/gpio.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2400-gpio.c
+/* linux/arch/arm/mach-s3c2400/gpio.c
  *
  * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
  *
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 0ab590e..016b53f 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -1,179 +1,8 @@
-if ARCH_S3C2410
-
-menu "S3C24XX Implementations"
-
-config MACH_AML_M5900
-	bool "AML M5900 Series"
-	select CPU_S3C2410
-	select PM_SIMTEC if PM
-	help
-	   Say Y here if you are using the American Microsystems M5900 Series
-           <http://www.amltd.com>
-
-config MACH_ANUBIS
-	bool "Simtec Electronics ANUBIS"
-	select CPU_S3C2440
-	select PM_SIMTEC if PM
-	help
-	  Say Y here if you are using the Simtec Electronics ANUBIS
-	  development system
-
-config MACH_OSIRIS
-	bool "Simtec IM2440D20 (OSIRIS) module"
-	select CPU_S3C2440
-	select PM_SIMTEC if PM
-	help
-	  Say Y here if you are using the Simtec IM2440D20 module, also
-	  known as the Osiris.
-
-config ARCH_BAST
-	bool "Simtec Electronics BAST (EB2410ITX)"
-	select CPU_S3C2410
-	select PM_SIMTEC if PM
-	select ISA
-	help
-	  Say Y here if you are using the Simtec Electronics EB2410ITX
-	  development board (also known as BAST)
-
-	  Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
-
-config BAST_PC104_IRQ
-	bool "BAST PC104 IRQ support"
-	depends on ARCH_BAST
-	default y
-	help
-	  Say Y	here to enable the PC104 IRQ routing on the
-	  Simtec BAST (EB2410ITX)
-
-config PM_H1940
-	bool
-	help
-	  Internal node for H1940 and related PM
-
-config ARCH_H1940
-	bool "IPAQ H1940"
-	select CPU_S3C2410
-	select PM_H1940 if PM
-	help
-	  Say Y here if you are using the HP IPAQ H1940
-
-	  <http://www.handhelds.org/projects/h1940.html>.
-
-config MACH_N30
-	bool "Acer N30"
-	select CPU_S3C2410
-	help
-	  Say Y here if you are using the Acer N30
-
-	  <http://zoo.weinigel.se/n30>.
-
-config MACH_SMDK
-	bool
-	help
-	  Common machine code for SMDK2410 and SMDK2440
-
-config ARCH_SMDK2410
-	bool "SMDK2410/A9M2410"
-	select CPU_S3C2410
-	select MACH_SMDK
-	help
-	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
-           <http://www.fsforth.de>
-
-config ARCH_S3C2440
-	bool "SMDK2440"
-	select CPU_S3C2440
-	select MACH_SMDK
-	help
-	  Say Y here if you are using the SMDK2440.
-
-config SMDK2440_CPU2440
-	bool "SMDK2440 with S3C2440 CPU module"
-	depends on ARCH_S3C2440
-	default y if ARCH_S3C2440
-	select CPU_S3C2440
-
-config SMDK2440_CPU2442
-	bool "SMDM2440 with S3C2442 CPU module"
-	depends on ARCH_S3C2440
-	select CPU_S3C2442
-
-config MACH_S3C2413
-	bool
-	help
-	  Internal node for S3C2413 version of SMDK2413, so that
-	  machine_is_s3c2413() will work when MACH_SMDK2413 is
-	  selected
-
-config MACH_SMDK2413
-	bool "SMDK2413"
-	select CPU_S3C2412
-	select MACH_S3C2413
-	select MACH_SMDK
-	help
-	  Say Y here if you are using an SMDK2413
-
-config MACH_VR1000
-	bool "Thorcom VR1000"
-	select PM_SIMTEC if PM
-	select CPU_S3C2410
-	help
-	  Say Y here if you are using the Thorcom VR1000 board.
-
-	  This linux port is currently being maintained by Simtec, on behalf
-	  of Thorcom. Any queries, please contact Thorcom first.
-
-config MACH_RX3715
-	bool "HP iPAQ rx3715"
-	select CPU_S3C2440
-	select PM_H1940 if PM
-	help
-	  Say Y here if you are using the HP iPAQ rx3715.
-
-	  See <http://www.handhelds.org/projects/rx3715.html> for more
-	  information on this project
-
-config MACH_OTOM
- 	bool "NexVision OTOM Board"
- 	select CPU_S3C2410
-	help
- 	  Say Y here if you are using the Nex Vision OTOM board
-
-config MACH_NEXCODER_2440
- 	bool "NexVision NEXCODER 2440 Light Board"
- 	select CPU_S3C2440
-	help
- 	  Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
-
-config MACH_VSTMS
-	bool "VMSTMS"
-	select CPU_S3C2412
-	help
-	  Say Y here if you are using an VSTMS board
-
-endmenu
-
-config S3C2410_CLOCK
-	bool
-	help
-	  Clock code for the S3C2410, and similar processors
-
-config S3C2410_GPIO
-	bool
-	help
-	  GPIO code for S3C2410 and similar processors
-
-config S3C2410_PM
-	bool
-	help
-	  Power Management code common to S3C2410 and better
-
-config CPU_S3C2410_DMA
-	bool
-	depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
-	default y if CPU_S3C2410 || CPU_S3C2442
-	help
-	  DMA device selection for S3C2410 and compatible CPUs
+# arch/arm/mach-s3c2410/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
 
 config CPU_S3C2410
 	bool
@@ -185,158 +14,95 @@
 	  Support for S3C2410 and S3C2410A family from the S3C24XX line
 	  of Samsung Mobile CPUs.
 
-# internal node to signify if we are only dealing with an S3C2412
-
-config CPU_S3C2412_ONLY
+config CPU_S3C2410_DMA
 	bool
-	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
-		   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
-	default y if CPU_S3C2412
+	depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
+	default y if CPU_S3C2410 || CPU_S3C2442
+	help
+	  DMA device selection for S3C2410 and compatible CPUs
 
-config S3C2412_PM
+config S3C2410_PM
 	bool
 	help
-	  Internal config node to apply S3C2412 power management
+	  Power Management code common to S3C2410 and better
 
-config S3C2412_DMA
-	bool
-	depends on CPU_S3C2412
-	help
-	  Internal config node for S3C2412 DMA support
-
-config CPU_S3C2412
-	bool
-	depends on ARCH_S3C2410
-	select S3C2412_PM if PM
-	select S3C2412_DMA if S3C2410_DMA
-	help
-	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
-
-config CPU_S3C244X
-	bool
-	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
-	help
-	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
-
-config S3C2440_DMA
-	bool
-	depends on ARCH_S3C2410 && CPU_S3C24405B
-	help
-	  Support for S3C2440 specific DMA code5A
-
-config CPU_S3C2440
-	bool
-	depends on ARCH_S3C2410
-	select S3C2410_CLOCK
-	select S3C2410_PM if PM
-	select S3C2410_GPIO
-	select S3C2440_DMA if S3C2410_DMA
-	select CPU_S3C244X
-	help
-	  Support for S3C2440 Samsung Mobile CPU based systems.
-
-config CPU_S3C2442
-	bool
-	depends on ARCH_S3C2420
-	select S3C2410_CLOCK
-	select S3C2410_GPIO
-	select S3C2410_PM if PM
-	select CPU_S3C244X
-	help
-	  Support for S3C2442 Samsung Mobile CPU based systems.
-
-comment "S3C2410 Boot"
-
-config S3C2410_BOOT_WATCHDOG
-	bool "S3C2410 Initialisation watchdog"
-	depends on ARCH_S3C2410 && S3C2410_WATCHDOG
-	help
-	  Say y to enable the watchdog during the kernel decompression
-	  stage. If the kernel fails to uncompress, then the watchdog
-	  will trigger a reset and the system should restart.
-
-	  Although this uses the same hardware unit as the kernel watchdog
-	  driver, it is not a replacement for it. If you use this option,
-	  you will have to use the watchdg driver to either stop the timeout
-	  or restart it. If you do not, then your kernel will reboot after
-	  startup.
-
-	  The driver uses a fixed timeout value, so the exact time till the
-	  system resets depends on the value of PCLK. The timeout on an
-	  200MHz s3c2410 should be about 30 seconds.
-
-config S3C2410_BOOT_ERROR_RESET
-	bool "S3C2410 Reboot on decompression error"
-	depends on ARCH_S3C2410
-	help
-	  Say y here to use the watchdog to reset the system if the
-	  kernel decompressor detects an error during decompression.
-
-
-comment "S3C2410 Setup"
-
-config S3C2410_DMA
-	bool "S3C2410 DMA support"
-	depends on ARCH_S3C2410
-	help
-	  S3C2410 DMA support. This is needed for drivers like sound which
-	  use the S3C2410's DMA system to move data to and from the
-	  peripheral blocks.
-
-config S3C2410_DMA_DEBUG
-	bool "S3C2410 DMA support debug"
-	depends on ARCH_S3C2410 && S3C2410_DMA
-	help
-	  Enable debugging output for the DMA code. This option sends info
-	  to the kernel log, at priority KERN_DEBUG.
-
-	  Note, it is easy to create and fill the log buffer in a small
-	  amount of time, as well as using an significant percentage of
-	  the CPU time doing so.
-
-config S3C2410_PM_DEBUG
-	bool "S3C2410 PM Suspend debug"
-	depends on ARCH_S3C2410 && PM
-	help
-	  Say Y here if you want verbose debugging from the PM Suspend and
-	  Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
-	  for more information.
-
-config S3C2410_PM_CHECK
-	bool "S3C2410 PM Suspend Memory CRC"
-	depends on ARCH_S3C2410 && PM && CRC32
-	help
- 	  Enable the PM code's memory area checksum over sleep. This option
-	  will generate CRCs of all blocks of memory, and store them before
-	  going to sleep. The blocks are then checked on resume for any
-	  errors.
-
-config S3C2410_PM_CHECK_CHUNKSIZE
-	int "S3C2410 PM Suspend CRC Chunksize (KiB)"
-	depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
-	default 64
-	help
-	  Set the chunksize in Kilobytes of the CRC for checking memory
-	  corruption over suspend and resume. A smaller value will mean that
-	  the CRC data block will take more memory, but wil identify any
-	  faults with better precision.
-
-config PM_SIMTEC
+config S3C2410_GPIO
 	bool
 	help
-	  Common power management code for systems that are
-	  compatible with the Simtec style of power management
+	  GPIO code for S3C2410 and similar processors
 
-config S3C2410_LOWLEVEL_UART_PORT
-	int "S3C2410 UART to use for low-level messages"
-	default 0
+config S3C2410_CLOCK
+	bool
 	help
-	  Choice of which UART port to use for the low-level messages,
-	  such as the `Uncompressing...` at start time. The value of
-	  this configuration should be between zero and two. The port
-	  must have been initialised by the boot-loader before use.
+	  Clock code for the S3C2410, and similar processors
 
-	  Note, this does not affect the port used by the debug messages,
-	  which is a separate configuration.
 
-endif
+menu "S3C2410 Machines"
+
+config ARCH_SMDK2410
+	bool "SMDK2410/A9M2410"
+	select CPU_S3C2410
+	select MACH_SMDK
+	help
+	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
+           <http://www.fsforth.de>
+
+config ARCH_H1940
+	bool "IPAQ H1940"
+	select CPU_S3C2410
+	select PM_H1940 if PM
+	help
+	  Say Y here if you are using the HP IPAQ H1940
+
+config PM_H1940
+	bool
+	help
+	  Internal node for H1940 and related PM
+
+config MACH_N30
+	bool "Acer N30"
+	select CPU_S3C2410
+	help
+	  Say Y here if you are using the Acer N30
+
+config ARCH_BAST
+	bool "Simtec Electronics BAST (EB2410ITX)"
+	select CPU_S3C2410
+	select PM_SIMTEC if PM
+	select ISA
+	help
+	  Say Y here if you are using the Simtec Electronics EB2410ITX
+	  development board (also known as BAST)
+
+config MACH_OTOM
+ 	bool "NexVision OTOM Board"
+ 	select CPU_S3C2410
+	help
+ 	  Say Y here if you are using the Nex Vision OTOM board
+
+config MACH_AML_M5900
+	bool "AML M5900 Series"
+	select CPU_S3C2410
+	select PM_SIMTEC if PM
+	help
+	   Say Y here if you are using the American Microsystems M5900 Series
+           <http://www.amltd.com>
+
+config BAST_PC104_IRQ
+	bool "BAST PC104 IRQ support"
+	depends on ARCH_BAST
+	default y
+	help
+	  Say Y	here to enable the PC104 IRQ routing on the
+	  Simtec BAST (EB2410ITX)
+
+config MACH_VR1000
+	bool "Thorcom VR1000"
+	select PM_SIMTEC if PM
+	select CPU_S3C2410
+	help
+	  Say Y here if you are using the Thorcom VR1000 board.
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 1cc5feb..b33ac5b 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -1,85 +1,30 @@
-
+# arch/arm/mach-s3c2410/Makefile
 #
-# Makefile for the linux kernel.
+# Copyright 2007 Simtec Electronics
 #
+# Licensed under GPLv2
 
-# Object file lists.
-
-obj-y			:= cpu.o irq.o time.o gpio.o clock.o devs.o
-obj-m			:=
-obj-n			:=
-obj-			:=
-
-# DMA
-obj-$(CONFIG_S3C2410_DMA)	+= dma.o
-
-# S3C2400 support files
-obj-$(CONFIG_CPU_S3C2400)	+= s3c2400-gpio.o
-
-# S3C2410 support files
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
 
 obj-$(CONFIG_CPU_S3C2410)	+= s3c2410.o
-obj-$(CONFIG_CPU_S3C2410)	+= s3c2410-irq.o
+obj-$(CONFIG_CPU_S3C2410)	+= irq.o
+obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
+obj-$(CONFIG_CPU_S3C2410_DMA)	+= dma.o
+obj-$(CONFIG_S3C2410_PM)	+= pm.o sleep.o
+obj-$(CONFIG_S3C2410_GPIO)	+= gpio.o
+obj-$(CONFIG_S3C2410_CLOCK)	+= clock.o
 
-obj-$(CONFIG_S3C2410_PM)	+= s3c2410-pm.o s3c2410-sleep.o
-obj-$(CONFIG_S3C2410_GPIO)	+= s3c2410-gpio.o
-obj-$(CONFIG_CPU_S3C2410_DMA)	+= s3c2410-dma.o
+# Machine support
 
-# Power Management support
-
-obj-$(CONFIG_PM)		+= pm.o sleep.o
-obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
-obj-$(CONFIG_PM_H1940)		+= pm-h1940.o
-
-# S3C2412 support
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-irq.o
-obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-clock.o
-
-obj-$(CONFIG_S3C2412_PM)	+= s3c2412-pm.o
-obj-$(CONFIG_S3C2412_DMA)	+= s3c2412-dma.o
-
-#
-# S3C244X support
-
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o
-obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-irq.o
-
-# Clock control
-
-obj-$(CONFIG_S3C2410_CLOCK)	+= s3c2410-clock.o
-
-# S3C2440 support
-
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o s3c2440-dsc.o
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-irq.o
-obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-clock.o
-obj-$(CONFIG_S3C2440_DMA)	+= s3c2440-dma.o
-
-# S3C2442 support
-
-obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
-obj-$(CONFIG_CPU_S3C2442)	+= s3c2442-clock.o
-
-# bast extras
-
-obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
-
-# machine specific support
-
-obj-$(CONFIG_MACH_AML_M5900)	+= mach-amlm5900.o
-obj-$(CONFIG_MACH_ANUBIS)	+= mach-anubis.o
-obj-$(CONFIG_MACH_OSIRIS)	+= mach-osiris.o
-obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
-obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
-obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
-obj-$(CONFIG_MACH_SMDK2413)	+= mach-smdk2413.o
-obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
-obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
-obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
+obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
+obj-$(CONFIG_PM_H1940)		+= pm-h1940.o
+obj-$(CONFIG_MACH_N30)		+= mach-n30.o
+obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
 obj-$(CONFIG_MACH_OTOM)		+= mach-otom.o
-obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
-obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
-
-obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
\ No newline at end of file
+obj-$(CONFIG_MACH_AML_M5900)	+= mach-amlm5900.o
+obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
+obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index 379efe7..daeba42 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -39,7 +39,7 @@
 #include <asm/arch/bast-map.h>
 #include <asm/arch/bast-irq.h>
 
-#include "irq.h"
+#include <asm/plat-s3c24xx/irq.h>
 
 #if 0
 #include <asm/debug-ll.h>
diff --git a/arch/arm/mach-s3c2410/bast.h b/arch/arm/mach-s3c2410/bast.h
index e5d0331..e985437 100644
--- a/arch/arm/mach-s3c2410/bast.h
+++ b/arch/arm/mach-s3c2410/bast.h
@@ -1,2 +1,2 @@
-
+/* linux/arch/arm/mach-s3c2410/bast.h
 extern void bast_init_irq(void);
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index e13fb67..5b4831c 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -1,15 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/clock.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX Core clock control support
- *
- * Based on, and code from linux/arch/arm/mach-versatile/clock.c
- **
- **  Copyright (C) 2004 ARM Limited.
- **  Written by Deep Blue Solutions Limited.
- *
+ * S3C2410,S3C2440,S3C2442 Clock control support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,418 +26,251 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
 #include <linux/sysdev.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
 #include <linux/clk.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/mach/map.h>
 
 #include <asm/hardware.h>
-#include <asm/irq.h>
 #include <asm/io.h>
 
+#include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-/* clock information */
-
-static LIST_HEAD(clocks);
-
-DEFINE_MUTEX(clocks_mutex);
-
-/* enable and disable calls for use with the clk struct */
-
-static int clk_null_enable(struct clk *clk, int enable)
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
 {
-	return 0;
-}
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
 
-/* Clock API calls */
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p;
-	struct clk *clk = ERR_PTR(-ENOENT);
-	int idno;
-
-	if (dev == NULL || dev->bus != &platform_bus_type)
-		idno = -1;
-	else
-		idno = to_platform_device(dev)->id;
-
-	mutex_lock(&clocks_mutex);
-
-	list_for_each_entry(p, &clocks, list) {
-		if (p->id == idno &&
-		    strcmp(id, p->name) == 0 &&
-		    try_module_get(p->owner)) {
-			clk = p;
-			break;
-		}
-	}
-
-	/* check for the case where a device was supplied, but the
-	 * clock that was being searched for is not device specific */
-
-	if (IS_ERR(clk)) {
-		list_for_each_entry(p, &clocks, list) {
-			if (p->id == -1 && strcmp(id, p->name) == 0 &&
-			    try_module_get(p->owner)) {
-				clk = p;
-				break;
-			}
-		}
-	}
-
-	mutex_unlock(&clocks_mutex);
-	return clk;
-}
-
-void clk_put(struct clk *clk)
-{
-	module_put(clk->owner);
-}
-
-int clk_enable(struct clk *clk)
-{
-	if (IS_ERR(clk) || clk == NULL)
-		return -EINVAL;
-
-	clk_enable(clk->parent);
-
-	mutex_lock(&clocks_mutex);
-
-	if ((clk->usage++) == 0)
-		(clk->enable)(clk, 1);
-
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-
-void clk_disable(struct clk *clk)
-{
-	if (IS_ERR(clk) || clk == NULL)
-		return;
-
-	mutex_lock(&clocks_mutex);
-
-	if ((--clk->usage) == 0)
-		(clk->enable)(clk, 0);
-
-	mutex_unlock(&clocks_mutex);
-	clk_disable(clk->parent);
-}
-
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (IS_ERR(clk))
-		return 0;
-
-	if (clk->rate != 0)
-		return clk->rate;
-
-	if (clk->get_rate != NULL)
-		return (clk->get_rate)(clk);
-
-	if (clk->parent != NULL)
-		return clk_get_rate(clk->parent);
-
-	return clk->rate;
-}
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (!IS_ERR(clk) && clk->round_rate)
-		return (clk->round_rate)(clk, rate);
-
-	return rate;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int ret;
-
-	if (IS_ERR(clk))
-		return -EINVAL;
-
-	mutex_lock(&clocks_mutex);
-	ret = (clk->set_rate)(clk, rate);
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-	return clk->parent;
-}
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret = 0;
-
-	if (IS_ERR(clk))
-		return -EINVAL;
-
-	mutex_lock(&clocks_mutex);
-
-	if (clk->set_parent)
-		ret = (clk->set_parent)(clk, parent);
-
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_get);
-EXPORT_SYMBOL(clk_put);
-EXPORT_SYMBOL(clk_enable);
-EXPORT_SYMBOL(clk_disable);
-EXPORT_SYMBOL(clk_get_rate);
-EXPORT_SYMBOL(clk_round_rate);
-EXPORT_SYMBOL(clk_set_rate);
-EXPORT_SYMBOL(clk_get_parent);
-EXPORT_SYMBOL(clk_set_parent);
-
-/* base clocks */
-
-struct clk clk_xtal = {
-	.name		= "xtal",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_mpll = {
-	.name		= "mpll",
-	.id		= -1,
-};
-
-struct clk clk_upll = {
-	.name		= "upll",
-	.id		= -1,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_f = {
-	.name		= "fclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= &clk_mpll,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_h = {
-	.name		= "hclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_p = {
-	.name		= "pclk",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= NULL,
-	.ctrlbit	= 0,
-};
-
-struct clk clk_usb_bus = {
-	.name		= "usb-bus",
-	.id		= -1,
-	.rate		= 0,
-	.parent		= &clk_upll,
-};
-
-/* clocks that could be registered by external code */
-
-static int s3c24xx_dclk_enable(struct clk *clk, int enable)
-{
-	unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+	clkcon = __raw_readl(S3C2410_CLKCON);
 
 	if (enable)
-		dclkcon |= clk->ctrlbit;
+		clkcon |= clocks;
 	else
-		dclkcon &= ~clk->ctrlbit;
+		clkcon &= ~clocks;
 
-	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+	/* ensure none of the special function bits set */
+	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
 
 	return 0;
 }
 
-static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+static int s3c2410_upll_enable(struct clk *clk, int enable)
 {
-	unsigned long dclkcon;
-	unsigned int uclk;
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long orig = clkslow;
 
-	if (parent == &clk_upll)
-		uclk = 1;
-	else if (parent == &clk_p)
-		uclk = 0;
+	if (enable)
+		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
 	else
-		return -EINVAL;
+		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
 
-	clk->parent = parent;
+	__raw_writel(clkslow, S3C2410_CLKSLOW);
 
-	dclkcon = __raw_readl(S3C24XX_DCLKCON);
+	/* if we started the UPLL, then allow to settle */
 
-	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
-		if (uclk)
-			dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
-		else
-			dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
-	} else {
-		if (uclk)
-			dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
-		else
-			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
+	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+		udelay(200);
+
+	return 0;
+}
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	},
+};
+
+/* s3c2410_baseclk_add()
+ *
+ * Add all the clocks used by the s3c2410 or compatible CPUs
+ * such as the S3C2440 and S3C2442.
+ *
+ * We cannot use a system device as we are needed before any
+ * of the init-calls that initialise the devices are actually
+ * done.
+*/
+
+int __init s3c2410_baseclk_add(void)
+{
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	struct clk *xtal;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2410_upll_enable;
+
+	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+		printk(KERN_ERR "failed to register usb bus clock\n");
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
 	}
 
-	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
 
-	return 0;
-}
+	/* install (and disable) the clocks we do not need immediately */
 
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
 
-static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
-{
-	unsigned long mask;
-	unsigned long source;
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
 
-	/* calculate the MISCCR setting for the clock */
-
-	if (parent == &clk_xtal)
-		source = S3C2410_MISCCR_CLK0_MPLL;
-	else if (parent == &clk_upll)
-		source = S3C2410_MISCCR_CLK0_UPLL;
-	else if (parent == &clk_f)
-		source = S3C2410_MISCCR_CLK0_FCLK;
-	else if (parent == &clk_h)
-		source = S3C2410_MISCCR_CLK0_HCLK;
-	else if (parent == &clk_p)
-		source = S3C2410_MISCCR_CLK0_PCLK;
-	else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
-		source = S3C2410_MISCCR_CLK0_DCLK0;
-	else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
-		source = S3C2410_MISCCR_CLK0_DCLK0;
-	else
-		return -EINVAL;
-
-	clk->parent = parent;
-
-	if (clk == &s3c24xx_dclk0)
-		mask = S3C2410_MISCCR_CLK0_MASK;
-	else {
-		source <<= 4;
-		mask = S3C2410_MISCCR_CLK1_MASK;
+		s3c2410_clkcon_enable(clkp, 0);
 	}
 
-	s3c2410_modify_misccr(mask, source);
-	return 0;
-}
+	/* show the clock-slow value */
 
-/* external clock definitions */
+	xtal = clk_get(NULL, "xtal");
 
-struct clk s3c24xx_dclk0 = {
-	.name		= "dclk0",
-	.id		= -1,
-	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
-	.enable	        = s3c24xx_dclk_enable,
-	.set_parent	= s3c24xx_dclk_setparent,
-};
-
-struct clk s3c24xx_dclk1 = {
-	.name		= "dclk1",
-	.id		= -1,
-	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
-	.enable		= s3c24xx_dclk_enable,
-	.set_parent	= s3c24xx_dclk_setparent,
-};
-
-struct clk s3c24xx_clkout0 = {
-	.name		= "clkout0",
-	.id		= -1,
-	.set_parent	= s3c24xx_clkout_setparent,
-};
-
-struct clk s3c24xx_clkout1 = {
-	.name		= "clkout1",
-	.id		= -1,
-	.set_parent	= s3c24xx_clkout_setparent,
-};
-
-struct clk s3c24xx_uclk = {
-	.name		= "uclk",
-	.id		= -1,
-};
-
-/* initialise the clock system */
-
-int s3c24xx_register_clock(struct clk *clk)
-{
-	clk->owner = THIS_MODULE;
-
-	if (clk->enable == NULL)
-		clk->enable = clk_null_enable;
-
-	/* add to the list of available clocks */
-
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->list, &clocks);
-	mutex_unlock(&clocks_mutex);
-
-	return 0;
-}
-
-/* initalise all the clocks */
-
-int __init s3c24xx_setup_clocks(unsigned long xtal,
-				unsigned long fclk,
-				unsigned long hclk,
-				unsigned long pclk)
-{
-	printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
-
-	/* initialise the main system clocks */
-
-	clk_xtal.rate = xtal;
-	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
-
-	clk_mpll.rate = fclk;
-	clk_h.rate = hclk;
-	clk_p.rate = pclk;
-	clk_f.rate = fclk;
-
-	/* assume uart clocks are correctly setup */
-
-	/* register our clocks */
-
-	if (s3c24xx_register_clock(&clk_xtal) < 0)
-		printk(KERN_ERR "failed to register master xtal\n");
-
-	if (s3c24xx_register_clock(&clk_mpll) < 0)
-		printk(KERN_ERR "failed to register mpll clock\n");
-
-	if (s3c24xx_register_clock(&clk_upll) < 0)
-		printk(KERN_ERR "failed to register upll clock\n");
-
-	if (s3c24xx_register_clock(&clk_f) < 0)
-		printk(KERN_ERR "failed to register cpu fclk\n");
-
-	if (s3c24xx_register_clock(&clk_h) < 0)
-		printk(KERN_ERR "failed to register cpu hclk\n");
-
-	if (s3c24xx_register_clock(&clk_p) < 0)
-		printk(KERN_ERR "failed to register cpu pclk\n");
+	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+	       print_mhz(clk_get_rate(xtal) /
+			 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
 
 	return 0;
 }
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index fa860e7..22c6136 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/dma.c
  *
- * Copyright (c) 2003-2005,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 DMA core
+ * S3C2410 DMA selection
  *
  * http://armlinux.simtec.co.uk/
  *
@@ -12,1430 +12,150 @@
  * published by the Free Software Foundation.
 */
 
-
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-#define DEBUG
-#endif
-
-#include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
 #include <linux/sysdev.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
+#include <linux/serial_core.h>
 
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
 #include <asm/dma.h>
+#include <asm/arch/dma.h>
+#include <asm/plat-s3c24xx/dma.h>
 
-#include <asm/mach/dma.h>
-#include <asm/arch/map.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "dma.h"
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-ac97.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-sdi.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-spi.h>
 
-/* io map for dma */
-static void __iomem *dma_base;
-static struct kmem_cache *dma_kmem;
-
-struct s3c24xx_dma_selection dma_sel;
-
-/* dma channel state information */
-struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
-
-/* debugging functions */
-
-#define BUF_MAGIC (0xcafebabe)
-
-#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
-
-#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
-
-#if 1
-#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
-#else
-static inline void
-dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
-{
-	pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
-	writel(val, dma_regaddr(chan, reg));
-}
-#endif
-
-#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
-
-/* captured register state for debug */
-
-struct s3c2410_dma_regstate {
-	unsigned long         dcsrc;
-	unsigned long         disrc;
-	unsigned long         dstat;
-	unsigned long         dcon;
-	unsigned long         dmsktrig;
+static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
+	[DMACH_XD0] = {
+		.name		= "xdreq0",
+		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
+	},
+	[DMACH_XD1] = {
+		.name		= "xdreq1",
+		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
+	},
+	[DMACH_SDI] = {
+		.name		= "sdi",
+		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_SPI0] = {
+		.name		= "spi0",
+		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
+	},
+	[DMACH_SPI1] = {
+		.name		= "spi1",
+		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
+		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
+	},
+	[DMACH_UART0] = {
+		.name		= "uart0",
+		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
+	},
+	[DMACH_UART1] = {
+		.name		= "uart1",
+		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
+	},
+      	[DMACH_UART2] = {
+		.name		= "uart2",
+		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
+		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
+	},
+	[DMACH_TIMER] = {
+		.name		= "timer",
+		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
+		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
+	},
+	[DMACH_I2S_IN] = {
+		.name		= "i2s-sdi",
+		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
+		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_I2S_OUT] = {
+		.name		= "i2s-sdo",
+		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
+		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	},
+	[DMACH_USB_EP1] = {
+		.name		= "usb-ep1",
+		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP2] = {
+		.name		= "usb-ep2",
+		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP3] = {
+		.name		= "usb-ep3",
+		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
+	},
+	[DMACH_USB_EP4] = {
+		.name		= "usb-ep4",
+		.channels[3]	=S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
+	},
 };
 
-#ifdef CONFIG_S3C2410_DMA_DEBUG
-
-/* dmadbg_showregs
- *
- * simple debug routine to print the current state of the dma registers
-*/
-
-static void
-dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
+static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
+			       struct s3c24xx_dma_map *map)
 {
-	regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
-	regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
-	regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
-	regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
-	regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
 }
 
-static void
-dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
-		 struct s3c2410_dma_regstate *regs)
-{
-	printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
-	       chan->number, fname, line,
-	       regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
-	       regs->dcon);
-}
-
-static void
-dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
-	struct s3c2410_dma_regstate state;
-
-	dmadbg_capture(chan, &state);
-
-	printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
-	       chan->number, fname, line, chan->load_state,
-	       chan->curr, chan->next, chan->end);
-
-	dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-static void
-dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
-{
-	struct s3c2410_dma_regstate state;
-
-	dmadbg_capture(chan, &state);
-	dmadbg_dumpregs(fname, line, chan, &state);
-}
-
-#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
-#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
-#else
-#define dbg_showregs(chan) do { } while(0)
-#define dbg_showchan(chan) do { } while(0)
-#endif /* CONFIG_S3C2410_DMA_DEBUG */
-
-static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
-
-/* lookup_dma_channel
- *
- * change the dma channel number given into a real dma channel id
-*/
-
-static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
-{
-	if (channel & DMACH_LOW_LEVEL)
-		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
-	else
-		return dma_chan_map[channel];
-}
-
-/* s3c2410_dma_stats_timeout
- *
- * Update DMA stats from timeout info
-*/
-
-static void
-s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
-{
-	if (stats == NULL)
-		return;
-
-	if (val > stats->timeout_longest)
-		stats->timeout_longest = val;
-	if (val < stats->timeout_shortest)
-		stats->timeout_shortest = val;
-
-	stats->timeout_avg += val;
-}
-
-/* s3c2410_dma_waitforload
- *
- * wait for the DMA engine to load a buffer, and update the state accordingly
-*/
-
-static int
-s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
-{
-	int timeout = chan->load_timeout;
-	int took;
-
-	if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
-		printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
-		return 0;
-	}
-
-	if (chan->stats != NULL)
-		chan->stats->loads++;
-
-	while (--timeout > 0) {
-		if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
-			took = chan->load_timeout - timeout;
-
-			s3c2410_dma_stats_timeout(chan->stats, took);
-
-			switch (chan->load_state) {
-			case S3C2410_DMALOAD_1LOADED:
-				chan->load_state = S3C2410_DMALOAD_1RUNNING;
-				break;
-
-			default:
-				printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
-			}
-
-			return 1;
-		}
-	}
-
-	if (chan->stats != NULL) {
-		chan->stats->timeout_failed++;
-	}
-
-	return 0;
-}
-
-
-
-/* s3c2410_dma_loadbuffer
- *
- * load a buffer, and update the channel state
-*/
-
-static inline int
-s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
-		       struct s3c2410_dma_buf *buf)
-{
-	unsigned long reload;
-
-	pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
-		 buf, (unsigned long)buf->data, buf->size);
-
-	if (buf == NULL) {
-		dmawarn("buffer is NULL\n");
-		return -EINVAL;
-	}
-
-	/* check the state of the channel before we do anything */
-
-	if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-		dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
-	}
-
-	if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
-		dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
-	}
-
-	/* it would seem sensible if we are the last buffer to not bother
-	 * with the auto-reload bit, so that the DMA engine will not try
-	 * and load another transfer after this one has finished...
-	 */
-	if (chan->load_state == S3C2410_DMALOAD_NONE) {
-		pr_debug("load_state is none, checking for noreload (next=%p)\n",
-			 buf->next);
-		reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
-	} else {
-		//pr_debug("load_state is %d => autoreload\n", chan->load_state);
-		reload = S3C2410_DCON_AUTORELOAD;
-	}
-
-	if ((buf->data & 0xf0000000) != 0x30000000) {
-		dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
-	}
-
-	writel(buf->data, chan->addr_reg);
-
-	dma_wrreg(chan, S3C2410_DMA_DCON,
-		  chan->dcon | reload | (buf->size/chan->xfer_unit));
-
-	chan->next = buf->next;
-
-	/* update the state of the channel */
-
-	switch (chan->load_state) {
-	case S3C2410_DMALOAD_NONE:
-		chan->load_state = S3C2410_DMALOAD_1LOADED;
-		break;
-
-	case S3C2410_DMALOAD_1RUNNING:
-		chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
-		break;
-
-	default:
-		dmawarn("dmaload: unknown state %d in loadbuffer\n",
-			chan->load_state);
-		break;
-	}
-
-	return 0;
-}
-
-/* s3c2410_dma_call_op
- *
- * small routine to call the op routine with the given op if it has been
- * registered
-*/
-
-static void
-s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
-{
-	if (chan->op_fn != NULL) {
-		(chan->op_fn)(chan, op);
-	}
-}
-
-/* s3c2410_dma_buffdone
- *
- * small wrapper to check if callback routine needs to be called, and
- * if so, call it
-*/
-
-static inline void
-s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
-		     enum s3c2410_dma_buffresult result)
-{
-#if 0
-	pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
-		 chan->callback_fn, buf, buf->id, buf->size, result);
-#endif
-
-	if (chan->callback_fn != NULL) {
-		(chan->callback_fn)(chan, buf->id, buf->size, result);
-	}
-}
-
-/* s3c2410_dma_start
- *
- * start a dma channel going
-*/
-
-static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
-{
-	unsigned long tmp;
-	unsigned long flags;
-
-	pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
-
-	local_irq_save(flags);
-
-	if (chan->state == S3C2410_DMA_RUNNING) {
-		pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	chan->state = S3C2410_DMA_RUNNING;
-
-	/* check wether there is anything to load, and if not, see
-	 * if we can find anything to load
-	 */
-
-	if (chan->load_state == S3C2410_DMALOAD_NONE) {
-		if (chan->next == NULL) {
-			printk(KERN_ERR "dma%d: channel has nothing loaded\n",
-			       chan->number);
-			chan->state = S3C2410_DMA_IDLE;
-			local_irq_restore(flags);
-			return -EINVAL;
-		}
-
-		s3c2410_dma_loadbuffer(chan, chan->next);
-	}
-
-	dbg_showchan(chan);
-
-	/* enable the channel */
-
-	if (!chan->irq_enabled) {
-		enable_irq(chan->irq);
-		chan->irq_enabled = 1;
-	}
-
-	/* start the channel going */
-
-	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-	tmp &= ~S3C2410_DMASKTRIG_STOP;
-	tmp |= S3C2410_DMASKTRIG_ON;
-	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
-	pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
-
-#if 0
-	/* the dma buffer loads should take care of clearing the AUTO
-	 * reloading feature */
-	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-	tmp &= ~S3C2410_DCON_NORELOAD;
-	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
-	s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
-
-	dbg_showchan(chan);
-
-	/* if we've only loaded one buffer onto the channel, then chec
-	 * to see if we have another, and if so, try and load it so when
-	 * the first buffer is finished, the new one will be loaded onto
-	 * the channel */
-
-	if (chan->next != NULL) {
-		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				pr_debug("%s: buff not yet loaded, no more todo\n",
-					 __FUNCTION__);
-			} else {
-				chan->load_state = S3C2410_DMALOAD_1RUNNING;
-				s3c2410_dma_loadbuffer(chan, chan->next);
-			}
-
-		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
-			s3c2410_dma_loadbuffer(chan, chan->next);
-		}
-	}
-
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-/* s3c2410_dma_canload
- *
- * work out if we can queue another buffer into the DMA engine
-*/
-
-static int
-s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
-{
-	if (chan->load_state == S3C2410_DMALOAD_NONE ||
-	    chan->load_state == S3C2410_DMALOAD_1RUNNING)
-		return 1;
-
-	return 0;
-}
-
-/* s3c2410_dma_enqueue
- *
- * queue an given buffer for dma transfer.
- *
- * id         the device driver's id information for this buffer
- * data       the physical address of the buffer data
- * size       the size of the buffer in bytes
- *
- * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
- * is checked, and if set, the channel is started. If this flag isn't set,
- * then an error will be returned.
- *
- * It is possible to queue more than one DMA buffer onto a channel at
- * once, and the code will deal with the re-loading of the next buffer
- * when necessary.
-*/
-
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
-			dma_addr_t data, int size)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-	struct s3c2410_dma_buf *buf;
-	unsigned long flags;
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: id=%p, data=%08x, size=%d\n",
-		 __FUNCTION__, id, (unsigned int)data, size);
-
-	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
-	if (buf == NULL) {
-		pr_debug("%s: out of memory (%ld alloc)\n",
-			 __FUNCTION__, (long)sizeof(*buf));
-		return -ENOMEM;
-	}
-
-	//pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
-	//dbg_showchan(chan);
-
-	buf->next  = NULL;
-	buf->data  = buf->ptr = data;
-	buf->size  = size;
-	buf->id    = id;
-	buf->magic = BUF_MAGIC;
-
-	local_irq_save(flags);
-
-	if (chan->curr == NULL) {
-		/* we've got nothing loaded... */
-		pr_debug("%s: buffer %p queued onto empty channel\n",
-			 __FUNCTION__, buf);
-
-		chan->curr = buf;
-		chan->end  = buf;
-		chan->next = NULL;
-	} else {
-		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
-			 chan->number, __FUNCTION__, buf);
-
-		if (chan->end == NULL)
-			pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
-				 chan->number, __FUNCTION__, chan);
-
-		chan->end->next = buf;
-		chan->end = buf;
-	}
-
-	/* if necessary, update the next buffer field */
-	if (chan->next == NULL)
-		chan->next = buf;
-
-	/* check to see if we can load a buffer */
-	if (chan->state == S3C2410_DMA_RUNNING) {
-		if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				printk(KERN_ERR "dma%d: loadbuffer:"
-				       "timeout loading buffer\n",
-				       chan->number);
-				dbg_showchan(chan);
-				local_irq_restore(flags);
-				return -EINVAL;
-			}
-		}
-
-		while (s3c2410_dma_canload(chan) && chan->next != NULL) {
-			s3c2410_dma_loadbuffer(chan, chan->next);
-		}
-	} else if (chan->state == S3C2410_DMA_IDLE) {
-		if (chan->flags & S3C2410_DMAF_AUTOSTART) {
-			s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
-		}
-	}
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_enqueue);
-
-static inline void
-s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
-{
-	int magicok = (buf->magic == BUF_MAGIC);
-
-	buf->magic = -1;
-
-	if (magicok) {
-		kmem_cache_free(dma_kmem, buf);
-	} else {
-		printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
-	}
-}
-
-/* s3c2410_dma_lastxfer
- *
- * called when the system is out of buffers, to ensure that the channel
- * is prepared for shutdown.
-*/
-
-static inline void
-s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
-{
-#if 0
-	pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
-		 chan->number, chan->load_state);
-#endif
-
-	switch (chan->load_state) {
-	case S3C2410_DMALOAD_NONE:
-		break;
-
-	case S3C2410_DMALOAD_1LOADED:
-		if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				/* flag error? */
-			printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-			       chan->number, __FUNCTION__);
-			return;
-		}
-		break;
-
-	case S3C2410_DMALOAD_1LOADED_1RUNNING:
-		/* I belive in this case we do not have anything to do
-		 * until the next buffer comes along, and we turn off the
-		 * reload */
-		return;
-
-	default:
-		pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
-			 chan->number, chan->load_state);
-		return;
-
-	}
-
-	/* hopefully this'll shut the damned thing up after the transfer... */
-	dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
-}
-
-
-#define dmadbg2(x...)
-
-static irqreturn_t
-s3c2410_dma_irq(int irq, void *devpw)
-{
-	struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
-	struct s3c2410_dma_buf  *buf;
-
-	buf = chan->curr;
-
-	dbg_showchan(chan);
-
-	/* modify the channel state */
-
-	switch (chan->load_state) {
-	case S3C2410_DMALOAD_1RUNNING:
-		/* TODO - if we are running only one buffer, we probably
-		 * want to reload here, and then worry about the buffer
-		 * callback */
-
-		chan->load_state = S3C2410_DMALOAD_NONE;
-		break;
-
-	case S3C2410_DMALOAD_1LOADED:
-		/* iirc, we should go back to NONE loaded here, we
-		 * had a buffer, and it was never verified as being
-		 * loaded.
-		 */
-
-		chan->load_state = S3C2410_DMALOAD_NONE;
-		break;
-
-	case S3C2410_DMALOAD_1LOADED_1RUNNING:
-		/* we'll worry about checking to see if another buffer is
-		 * ready after we've called back the owner. This should
-		 * ensure we do not wait around too long for the DMA
-		 * engine to start the next transfer
-		 */
-
-		chan->load_state = S3C2410_DMALOAD_1LOADED;
-		break;
-
-	case S3C2410_DMALOAD_NONE:
-		printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
-		       chan->number);
-		break;
-
-	default:
-		printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
-		       chan->number, chan->load_state);
-		break;
-	}
-
-	if (buf != NULL) {
-		/* update the chain to make sure that if we load any more
-		 * buffers when we call the callback function, things should
-		 * work properly */
-
-		chan->curr = buf->next;
-		buf->next  = NULL;
-
-		if (buf->magic != BUF_MAGIC) {
-			printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
-			       chan->number, __FUNCTION__, buf);
-			return IRQ_HANDLED;
-		}
-
-		s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
-
-		/* free resouces */
-		s3c2410_dma_freebuf(buf);
-	} else {
-	}
-
-	/* only reload if the channel is still running... our buffer done
-	 * routine may have altered the state by requesting the dma channel
-	 * to stop or shutdown... */
-
-	/* todo: check that when the channel is shut-down from inside this
-	 * function, we cope with unsetting reload, etc */
-
-	if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
-		unsigned long flags;
-
-		switch (chan->load_state) {
-		case S3C2410_DMALOAD_1RUNNING:
-			/* don't need to do anything for this state */
-			break;
-
-		case S3C2410_DMALOAD_NONE:
-			/* can load buffer immediately */
-			break;
-
-		case S3C2410_DMALOAD_1LOADED:
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				/* flag error? */
-				printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
-				       chan->number, __FUNCTION__);
-				return IRQ_HANDLED;
-			}
-
-			break;
-
-		case S3C2410_DMALOAD_1LOADED_1RUNNING:
-			goto no_load;
-
-		default:
-			printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
-			       chan->number, chan->load_state);
-			return IRQ_HANDLED;
-		}
-
-		local_irq_save(flags);
-		s3c2410_dma_loadbuffer(chan, chan->next);
-		local_irq_restore(flags);
-	} else {
-		s3c2410_dma_lastxfer(chan);
-
-		/* see if we can stop this channel.. */
-		if (chan->load_state == S3C2410_DMALOAD_NONE) {
-			pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
-				 chan->number, jiffies);
-			s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
-					 S3C2410_DMAOP_STOP);
-		}
-	}
-
- no_load:
-	return IRQ_HANDLED;
-}
-
-static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
-
-/* s3c2410_request_dma
- *
- * get control of an dma channel
-*/
-
-int s3c2410_dma_request(unsigned int channel,
-			struct s3c2410_dma_client *client,
-			void *dev)
-{
-	struct s3c2410_dma_chan *chan;
-	unsigned long flags;
-	int err;
-
-	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
-		 channel, client->name, dev);
-
-	local_irq_save(flags);
-
-	chan = s3c2410_dma_map_channel(channel);
-	if (chan == NULL) {
-		local_irq_restore(flags);
-		return -EBUSY;
-	}
-
-	dbg_showchan(chan);
-
-	chan->client = client;
-	chan->in_use = 1;
-
-	if (!chan->irq_claimed) {
-		pr_debug("dma%d: %s : requesting irq %d\n",
-			 channel, __FUNCTION__, chan->irq);
-
-		chan->irq_claimed = 1;
-		local_irq_restore(flags);
-
-		err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
-				  client->name, (void *)chan);
-
-		local_irq_save(flags);
-
-		if (err) {
-			chan->in_use = 0;
-			chan->irq_claimed = 0;
-			local_irq_restore(flags);
-
-			printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
-			       client->name, chan->irq, chan->number);
-			return err;
-		}
-
-		chan->irq_enabled = 1;
-	}
-
-	local_irq_restore(flags);
-
-	/* need to setup */
-
-	pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_request);
-
-/* s3c2410_dma_free
- *
- * release the given channel back to the system, will stop and flush
- * any outstanding transfers, and ensure the channel is ready for the
- * next claimant.
- *
- * Note, although a warning is currently printed if the freeing client
- * info is not the same as the registrant's client info, the free is still
- * allowed to go through.
-*/
-
-int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-	unsigned long flags;
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	local_irq_save(flags);
-
-	if (chan->client != client) {
-		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
-		       channel, chan->client, client);
-	}
-
-	/* sort out stopping and freeing the channel */
-
-	if (chan->state != S3C2410_DMA_IDLE) {
-		pr_debug("%s: need to stop dma channel %p\n",
-		       __FUNCTION__, chan);
-
-		/* possibly flush the channel */
-		s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
-	}
-
-	chan->client = NULL;
-	chan->in_use = 0;
-
-	if (chan->irq_claimed)
-		free_irq(chan->irq, (void *)chan);
-
-	chan->irq_claimed = 0;
-
-	if (!(channel & DMACH_LOW_LEVEL))
-		dma_chan_map[channel] = NULL;
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_free);
-
-static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
-{
-	unsigned long flags;
-	unsigned long tmp;
-
-	pr_debug("%s:\n", __FUNCTION__);
-
-	dbg_showchan(chan);
-
-	local_irq_save(flags);
-
-	s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
-
-	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-	tmp |= S3C2410_DMASKTRIG_STOP;
-	//tmp &= ~S3C2410_DMASKTRIG_ON;
-	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
-
-#if 0
-	/* should also clear interrupts, according to WinCE BSP */
-	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-	tmp |= S3C2410_DCON_NORELOAD;
-	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-#endif
-
-	/* should stop do this, or should we wait for flush? */
-	chan->state      = S3C2410_DMA_IDLE;
-	chan->load_state = S3C2410_DMALOAD_NONE;
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
-{
-	unsigned long tmp;
-	unsigned int timeout = 0x10000;
-
-	while (timeout-- > 0) {
-		tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
-
-		if (!(tmp & S3C2410_DMASKTRIG_ON))
-			return;
-	}
-
-	pr_debug("dma%d: failed to stop?\n", chan->number);
-}
-
-
-/* s3c2410_dma_flush
- *
- * stop the channel, and remove all current and pending transfers
-*/
-
-static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
-{
-	struct s3c2410_dma_buf *buf, *next;
-	unsigned long flags;
-
-	pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
-
-	dbg_showchan(chan);
-
-	local_irq_save(flags);
-
-	if (chan->state != S3C2410_DMA_IDLE) {
-		pr_debug("%s: stopping channel...\n", __FUNCTION__ );
-		s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
-	}
-
-	buf = chan->curr;
-	if (buf == NULL)
-		buf = chan->next;
-
-	chan->curr = chan->next = chan->end = NULL;
-
-	if (buf != NULL) {
-		for ( ; buf != NULL; buf = next) {
-			next = buf->next;
-
-			pr_debug("%s: free buffer %p, next %p\n",
-			       __FUNCTION__, buf, buf->next);
-
-			s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
-			s3c2410_dma_freebuf(buf);
-		}
-	}
-
-	dbg_showregs(chan);
-
-	s3c2410_dma_waitforstop(chan);
-
-#if 0
-	/* should also clear interrupts, according to WinCE BSP */
-	{
-		unsigned long tmp;
-
-		tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
-		tmp |= S3C2410_DCON_NORELOAD;
-		dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
-	}
-#endif
-
-	dbg_showregs(chan);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-int
-s3c2410_dma_started(struct s3c2410_dma_chan *chan)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	dbg_showchan(chan);
-
-	/* if we've only loaded one buffer onto the channel, then chec
-	 * to see if we have another, and if so, try and load it so when
-	 * the first buffer is finished, the new one will be loaded onto
-	 * the channel */
-
-	if (chan->next != NULL) {
-		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
-
-			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
-				pr_debug("%s: buff not yet loaded, no more todo\n",
-					 __FUNCTION__);
-			} else {
-				chan->load_state = S3C2410_DMALOAD_1RUNNING;
-				s3c2410_dma_loadbuffer(chan, chan->next);
-			}
-
-		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
-			s3c2410_dma_loadbuffer(chan, chan->next);
-		}
-	}
-
-
-	local_irq_restore(flags);
-
-	return 0;
-
-}
-
-int
-s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	switch (op) {
-	case S3C2410_DMAOP_START:
-		return s3c2410_dma_start(chan);
-
-	case S3C2410_DMAOP_STOP:
-		return s3c2410_dma_dostop(chan);
-
-	case S3C2410_DMAOP_PAUSE:
-	case S3C2410_DMAOP_RESUME:
-		return -ENOENT;
-
-	case S3C2410_DMAOP_FLUSH:
-		return s3c2410_dma_flush(chan);
-
-	case S3C2410_DMAOP_STARTED:
-		return s3c2410_dma_started(chan);
-
-	case S3C2410_DMAOP_TIMEOUT:
-		return 0;
-
-	}
-
-	return -ENOENT;      /* unknown, don't bother */
-}
-
-EXPORT_SYMBOL(s3c2410_dma_ctrl);
-
-/* DMA configuration for each channel
- *
- * DISRCC -> source of the DMA (AHB,APB)
- * DISRC  -> source address of the DMA
- * DIDSTC -> destination of the DMA (AHB,APD)
- * DIDST  -> destination address of the DMA
-*/
-
-/* s3c2410_dma_config
- *
- * xfersize:     size of unit in bytes (1,2,4)
- * dcon:         base value of the DCONx register
-*/
-
-int s3c2410_dma_config(dmach_t channel,
-		       int xferunit,
-		       int dcon)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
-		 __FUNCTION__, channel, xferunit, dcon);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
-
-	dcon |= chan->dcon & dma_sel.dcon_mask;
-
-	pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
-
-	switch (xferunit) {
-	case 1:
-		dcon |= S3C2410_DCON_BYTE;
-		break;
-
-	case 2:
-		dcon |= S3C2410_DCON_HALFWORD;
-		break;
-
-	case 4:
-		dcon |= S3C2410_DCON_WORD;
-		break;
-
-	default:
-		pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
-		return -EINVAL;
-	}
-
-	dcon |= S3C2410_DCON_HWTRIG;
-	dcon |= S3C2410_DCON_INTREQ;
-
-	pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
-
-	chan->dcon = dcon;
-	chan->xfer_unit = xferunit;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_config);
-
-int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
-
-	chan->flags = flags;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_setflags);
-
-
-/* do we need to protect the settings of the fields from
- * irq?
-*/
-
-int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
-
-	chan->op_fn = rtn;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_opfn);
-
-int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
-
-	chan->callback_fn = rtn;
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
-
-/* s3c2410_dma_devconfig
- *
- * configure the dma source/destination hardware type and address
- *
- * source:    S3C2410_DMASRC_HW: source is hardware
- *            S3C2410_DMASRC_MEM: source is memory
- *
- * hwcfg:     the value for xxxSTCn register,
- *            bit 0: 0=increment pointer, 1=leave pointer
- *            bit 1: 0=soucre is AHB, 1=soucre is APB
- *
- * devaddr:   physical address of the source
-*/
-
-int s3c2410_dma_devconfig(int channel,
-			  enum s3c2410_dmasrc source,
-			  int hwcfg,
-			  unsigned long devaddr)
-{
-	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
-		 __FUNCTION__, (int)source, hwcfg, devaddr);
-
-	chan->source = source;
-	chan->dev_addr = devaddr;
-
-	switch (source) {
-	case S3C2410_DMASRC_HW:
-		/* source is hardware */
-		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
-			 __FUNCTION__, devaddr, hwcfg);
-		dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
-		dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
-		dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
-
-		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
-		return 0;
-
-	case S3C2410_DMASRC_MEM:
-		/* source is memory */
-		pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
-			  __FUNCTION__, devaddr, hwcfg);
-		dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
-		dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
-		dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
-
-		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
-		return 0;
-	}
-
-	printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
-	return -EINVAL;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_devconfig);
-
-/* s3c2410_dma_getposition
- *
- * returns the current transfer points for the dma source and destination
-*/
-
-int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
-{
- 	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
-
-	if (chan == NULL)
-		return -EINVAL;
-
-	if (src != NULL)
- 		*src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
-
- 	if (dst != NULL)
- 		*dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
-
- 	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_dma_getposition);
-
-
-/* system device class */
-
-#ifdef CONFIG_PM
-
-static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
-{
-	struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
-
-	printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
-
-	if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
-		/* the dma channel is still working, which is probably
-		 * a bad thing to do over suspend/resume. We stop the
-		 * channel and assume that the client is either going to
-		 * retry after resume, or that it is broken.
-		 */
-
-		printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
-		       cp->number);
-
-		s3c2410_dma_dostop(cp);
-	}
-
-	return 0;
-}
-
-static int s3c2410_dma_resume(struct sys_device *dev)
-{
-	return 0;
-}
-
-#else
-#define s3c2410_dma_suspend NULL
-#define s3c2410_dma_resume  NULL
-#endif /* CONFIG_PM */
-
-struct sysdev_class dma_sysclass = {
-	set_kset_name("s3c24xx-dma"),
-	.suspend	= s3c2410_dma_suspend,
-	.resume		= s3c2410_dma_resume,
+static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
+	.select		= s3c2410_dma_select,
+	.dcon_mask	= 7 << 24,
+	.map		= s3c2410_dma_mappings,
+	.map_size	= ARRAY_SIZE(s3c2410_dma_mappings),
 };
 
-/* kmem cache implementation */
-
-static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
+static int s3c2410_dma_add(struct sys_device *sysdev)
 {
-	memset(p, 0, sizeof(struct s3c2410_dma_buf));
+	return s3c24xx_dma_init_map(&s3c2410_dma_sel);
 }
 
-/* initialisation code */
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_dma_driver = {
+	.add	= s3c2410_dma_add,
+};
 
-static int __init s3c2410_init_dma(void)
+static int __init s3c2410_dma_init(void)
 {
-	struct s3c2410_dma_chan *cp;
-	int channel;
-	int ret;
-
-	printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
-
-	dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
-	if (dma_base == NULL) {
-		printk(KERN_ERR "dma failed to remap register block\n");
-		return -ENOMEM;
-	}
-
-	printk("Registering sysclass\n");
-
-	ret = sysdev_class_register(&dma_sysclass);
-	if (ret != 0) {
-		printk(KERN_ERR "dma sysclass registration failed\n");
-		goto err;
-	}
-
-	dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
-				     SLAB_HWCACHE_ALIGN,
-				     s3c2410_dma_cache_ctor, NULL);
-
-	if (dma_kmem == NULL) {
-		printk(KERN_ERR "dma failed to make kmem cache\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
-		cp = &s3c2410_chans[channel];
-
-		memset(cp, 0, sizeof(struct s3c2410_dma_chan));
-
-		/* dma channel irqs are in order.. */
-		cp->number = channel;
-		cp->irq    = channel + IRQ_DMA0;
-		cp->regs   = dma_base + (channel*0x40);
-
-		/* point current stats somewhere */
-		cp->stats  = &cp->stats_store;
-		cp->stats_store.timeout_shortest = LONG_MAX;
-
-		/* basic channel configuration */
-
-		cp->load_timeout = 1<<18;
-
-		/* register system device */
-
-		cp->dev.cls = &dma_sysclass;
-		cp->dev.id  = channel;
-		ret = sysdev_register(&cp->dev);
-
-		printk("DMA channel %d at %p, irq %d\n",
-		       cp->number, cp->regs, cp->irq);
-	}
-
-	return 0;
-
- err:
-	kmem_cache_destroy(dma_kmem);
-	iounmap(dma_base);
-	dma_base = NULL;
-	return ret;
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
 }
 
-core_initcall(s3c2410_init_dma);
+arch_initcall(s3c2410_dma_init);
+#endif
 
-static inline int is_channel_valid(unsigned int channel)
+#if defined(CONFIG_CPU_S3C2442)
+/* S3C2442 DMA contains the same selection table as the S3C2410 */
+static struct sysdev_driver s3c2442_dma_driver = {
+	.add	= s3c2410_dma_add,
+};
+
+static int __init s3c2442_dma_init(void)
 {
-	return (channel & DMA_CH_VALID);
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
 }
 
-/* s3c2410_dma_map_channel()
- *
- * turn the virtual channel number into a real, and un-used hardware
- * channel.
- *
- * currently this code uses first-free channel from the specified harware
- * map, not taking into account anything that the board setup code may
- * have to say about the likely peripheral set to be in use.
-*/
+arch_initcall(s3c2442_dma_init);
+#endif
 
-struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
-{
-	struct s3c24xx_dma_map *ch_map;
-	struct s3c2410_dma_chan *dmach;
-	int ch;
-
-	if (dma_sel.map == NULL || channel > dma_sel.map_size)
-		return NULL;
-
-	ch_map = dma_sel.map + channel;
-
-	for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
-		if (!is_channel_valid(ch_map->channels[ch]))
-			continue;
-
-		if (s3c2410_chans[ch].in_use == 0) {
-			printk("mapped channel %d to %d\n", channel, ch);
-			break;
-		}
-	}
-
-	if (ch >= S3C2410_DMA_CHANNELS)
-		return NULL;
-
-	/* update our channel mapping */
-
-	dmach = &s3c2410_chans[ch];
-	dma_chan_map[channel] = dmach;
-
-	/* select the channel */
-
-	(dma_sel.select)(dmach, ch_map);
-
-	return dmach;
-}
-
-static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
-{
-	/* show the channel configuration */
-
-	printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
-	       (is_channel_valid(map->channels[0]) ? '0' : '-'),
-	       (is_channel_valid(map->channels[1]) ? '1' : '-'),
-	       (is_channel_valid(map->channels[2]) ? '2' : '-'),
-	       (is_channel_valid(map->channels[3]) ? '3' : '-'));
-}
-
-static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
-{
-	if (1)
-		s3c24xx_dma_show_ch(map, ch);
-
-	return 0;
-}
-
-int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
-{
-	struct s3c24xx_dma_map *nmap;
-	size_t map_sz = sizeof(*nmap) * sel->map_size;
-	int ptr;
-
-	nmap = kmalloc(map_sz, GFP_KERNEL);
-	if (nmap == NULL)
-		return -ENOMEM;
-
-	memcpy(nmap, sel->map, map_sz);
-	memcpy(&dma_sel, sel, sizeof(*sel));
-
-	dma_sel.map = nmap;
-
-	for (ptr = 0; ptr < sel->map_size; ptr++)
-		s3c24xx_dma_check_entry(nmap+ptr, ptr);
-
-	return 0;
-}
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index f6fb215..01e795d 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -1,9 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/gpio.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX GPIO support
+ * S3C2410 GPIO support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,8 +18,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
+ */
 
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -33,156 +32,40 @@
 
 #include <asm/arch/regs-gpio.h>
 
-void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+			   unsigned int config)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long mask;
-	unsigned long con;
+	void __iomem *reg = S3C24XX_EINFLT0;
 	unsigned long flags;
+	unsigned long val;
 
-	if (pin < S3C2410_GPIO_BANKB) {
-		mask = 1 << S3C2410_GPIO_OFFSET(pin);
-	} else {
-		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
-	}
+	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+		return -1;
 
-	switch (function) {
-	case S3C2410_GPIO_LEAVE:
-		mask = 0;
-		function = 0;
-		break;
+	config &= 0xff;
 
-	case S3C2410_GPIO_INPUT:
-	case S3C2410_GPIO_OUTPUT:
-	case S3C2410_GPIO_SFN2:
-	case S3C2410_GPIO_SFN3:
-		if (pin < S3C2410_GPIO_BANKB) {
-			function -= 1;
-			function &= 1;
-			function <<= S3C2410_GPIO_OFFSET(pin);
-		} else {
-			function &= 3;
-			function <<= S3C2410_GPIO_OFFSET(pin)*2;
-		}
-	}
-
-	/* modify the specified register wwith IRQs off */
+	pin -= S3C2410_GPG8;
+	reg += pin & ~3;
 
 	local_irq_save(flags);
 
-	con  = __raw_readl(base + 0x00);
-	con &= ~mask;
-	con |= function;
+	/* update filter width and clock source */
 
-	__raw_writel(con, base + 0x00);
+	val = __raw_readl(reg);
+	val &= ~(0xff << ((pin & 3) * 8));
+	val |= config << ((pin & 3) * 8);
+	__raw_writel(val, reg);
+
+	/* update filter enable */
+
+	val = __raw_readl(S3C24XX_EXTINT2);
+	val &= ~(1 << ((pin * 4) + 3));
+	val |= on << ((pin * 4) + 3);
+	__raw_writel(val, S3C24XX_EXTINT2);
 
 	local_irq_restore(flags);
+
+	return 0;
 }
 
-EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
-
-unsigned int s3c2410_gpio_getcfg(unsigned int pin)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long val = __raw_readl(base);
-
-	if (pin < S3C2410_GPIO_BANKB) {
-		val >>= S3C2410_GPIO_OFFSET(pin);
-		val &= 1;
-		val += 1;
-	} else {
-		val >>= S3C2410_GPIO_OFFSET(pin)*2;
-		val &= 3;
-	}
-
-	return val | S3C2410_GPIO_INPUT;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getcfg);
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-	unsigned long flags;
-	unsigned long up;
-
-	if (pin < S3C2410_GPIO_BANKB)
-		return;
-
-	local_irq_save(flags);
-
-	up = __raw_readl(base + 0x08);
-	up &= ~(1L << offs);
-	up |= to << offs;
-	__raw_writel(up, base + 0x08);
-
-	local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-	unsigned long flags;
-	unsigned long dat;
-
-	local_irq_save(flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offs);
-	dat |= to << offs;
-	__raw_writel(dat, base + 0x04);
-
-	local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-
-	return __raw_readl(base + 0x04) & (1<< offs);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-	unsigned long flags;
-	unsigned long misccr;
-
-	local_irq_save(flags);
-	misccr = __raw_readl(S3C24XX_MISCCR);
-	misccr &= ~clear;
-	misccr ^= change;
-	__raw_writel(misccr, S3C24XX_MISCCR);
-	local_irq_restore(flags);
-
-	return misccr;
-}
-
-EXPORT_SYMBOL(s3c2410_modify_misccr);
-
-int s3c2410_gpio_getirq(unsigned int pin)
-{
-	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
-		return -1;	/* not valid interrupts */
-
-	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
-		return -1;	/* not valid pin */
-
-	if (pin < S3C2410_GPF4)
-		return (pin - S3C2410_GPF0) + IRQ_EINT0;
-
-	if (pin < S3C2410_GPG0)
-		return (pin - S3C2410_GPF4) + IRQ_EINT4;
-
-	return (pin - S3C2410_GPG0) + IRQ_EINT8;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getirq);
+EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 3c0ed78..53cbdaa 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/irq.c
  *
- * Copyright (c) 2003,2004 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -17,37 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Changelog:
- *
- *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
- *                Fixed compile warnings
- *
- *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
- *                Fixed s3c_extirq_type
- *
- *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
- *                Addition of ADC/TC demux
- *
- *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
- *		  Fix for set_irq_type() on low EINT numbers
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *		  Tidy up KF's patch and sort out new release
- *
- *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
- *		  Add support for power management controls
- *
- *   04-Nov-2004  Ben Dooks
- *		  Fix standard IRQ wake for EINT0..4 and RTC
- *
- *   22-Feb-2005  Ben Dooks
- *		  Fixed edge-triggering on ADC IRQ
- *
- *   28-Jun-2005  Ben Dooks
- *		  Mark IRQ_LCD valid
- *
- *   25-Jul-2005  Ben Dooks
- *		  Split the S3C2440 IRQ code to seperate file
 */
 
 #include <linux/init.h>
@@ -57,745 +26,23 @@
 #include <linux/ptrace.h>
 #include <linux/sysdev.h>
 
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
-#include <asm/mach/irq.h>
-
-#include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
-
-/* wakeup irq control */
-
-#ifdef CONFIG_PM
-
-/* state for IRQs over sleep */
-
-/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
- *
- * set bit to 1 in allow bitfield to enable the wakeup settings on it
-*/
-
-unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
-unsigned long s3c_irqwake_intmask	= 0xffffffffL;
-unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
-unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
-
-int
-s3c_irq_wake(unsigned int irqno, unsigned int state)
+static int s3c2410_irq_add(struct sys_device *sysdev)
 {
-	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
-
-	if (!(s3c_irqwake_intallow & irqbit))
-		return -ENOENT;
-
-	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
-
-	if (!state)
-		s3c_irqwake_intmask |= irqbit;
-	else
-		s3c_irqwake_intmask &= ~irqbit;
-
 	return 0;
 }
 
-static int
-s3c_irqext_wake(unsigned int irqno, unsigned int state)
-{
-	unsigned long bit = 1L << (irqno - EXTINT_OFF);
-
-	if (!(s3c_irqwake_eintallow & bit))
-		return -ENOENT;
-
-	printk(KERN_INFO "wake %s for irq %d\n",
-	       state ? "enabled" : "disabled", irqno);
-
-	if (!state)
-		s3c_irqwake_eintmask |= bit;
-	else
-		s3c_irqwake_eintmask &= ~bit;
-
-	return 0;
-}
-
-#else
-#define s3c_irqext_wake NULL
-#define s3c_irq_wake NULL
-#endif
-
-
-static void
-s3c_irq_mask(unsigned int irqno)
-{
-	unsigned long mask;
-
-	irqno -= IRQ_EINT0;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	mask |= 1UL << irqno;
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-static inline void
-s3c_irq_ack(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c_irq_maskack(unsigned int irqno)
-{
-	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
-	unsigned long mask;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	__raw_writel(mask|bitval, S3C2410_INTMSK);
-
-	__raw_writel(bitval, S3C2410_SRCPND);
-	__raw_writel(bitval, S3C2410_INTPND);
-}
-
-
-static void
-s3c_irq_unmask(unsigned int irqno)
-{
-	unsigned long mask;
-
-	if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
-		irqdbf2("s3c_irq_unmask %d\n", irqno);
-
-	irqno -= IRQ_EINT0;
-
-	mask = __raw_readl(S3C2410_INTMSK);
-	mask &= ~(1UL << irqno);
-	__raw_writel(mask, S3C2410_INTMSK);
-}
-
-struct irq_chip s3c_irq_level_chip = {
-	.name		= "s3c-level",
-	.ack		= s3c_irq_maskack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake
+static struct sysdev_driver s3c2410_irq_driver = {
+	.add		= s3c2410_irq_add,
+	.suspend	= s3c24xx_irq_suspend,
+	.resume		= s3c24xx_irq_resume,
 };
 
-static struct irq_chip s3c_irq_chip = {
-	.name		= "s3c",
-	.ack		= s3c_irq_ack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake
-};
-
-static void
-s3c_irqext_mask(unsigned int irqno)
+static int s3c2410_irq_init(void)
 {
-	unsigned long mask;
-
-	irqno -= EXTINT_OFF;
-
-	mask = __raw_readl(S3C24XX_EINTMASK);
-	mask |= ( 1UL << irqno);
-	__raw_writel(mask, S3C24XX_EINTMASK);
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
 }
 
-static void
-s3c_irqext_ack(unsigned int irqno)
-{
-	unsigned long req;
-	unsigned long bit;
-	unsigned long mask;
-
-	bit = 1UL << (irqno - EXTINT_OFF);
-
-	mask = __raw_readl(S3C24XX_EINTMASK);
-
-	__raw_writel(bit, S3C24XX_EINTPEND);
-
-	req = __raw_readl(S3C24XX_EINTPEND);
-	req &= ~mask;
-
-	/* not sure if we should be acking the parent irq... */
-
-	if (irqno <= IRQ_EINT7 ) {
-		if ((req & 0xf0) == 0)
-			s3c_irq_ack(IRQ_EINT4t7);
-	} else {
-		if ((req >> 8) == 0)
-			s3c_irq_ack(IRQ_EINT8t23);
-	}
-}
-
-static void
-s3c_irqext_unmask(unsigned int irqno)
-{
-	unsigned long mask;
-
-	irqno -= EXTINT_OFF;
-
-	mask = __raw_readl(S3C24XX_EINTMASK);
-	mask &= ~( 1UL << irqno);
-	__raw_writel(mask, S3C24XX_EINTMASK);
-}
-
-int
-s3c_irqext_type(unsigned int irq, unsigned int type)
-{
-	void __iomem *extint_reg;
-	void __iomem *gpcon_reg;
-	unsigned long gpcon_offset, extint_offset;
-	unsigned long newvalue = 0, value;
-
-	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
-	{
-		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (irq - IRQ_EINT0) * 2;
-		extint_offset = (irq - IRQ_EINT0) * 4;
-	}
-	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
-	{
-		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C24XX_EXTINT0;
-		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
-		extint_offset = (irq - (EXTINT_OFF)) * 4;
-	}
-	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
-	{
-		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C24XX_EXTINT1;
-		gpcon_offset = (irq - IRQ_EINT8) * 2;
-		extint_offset = (irq - IRQ_EINT8) * 4;
-	}
-	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
-	{
-		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C24XX_EXTINT2;
-		gpcon_offset = (irq - IRQ_EINT8) * 2;
-		extint_offset = (irq - IRQ_EINT16) * 4;
-	} else
-		return -1;
-
-	/* Set the GPIO to external interrupt mode */
-	value = __raw_readl(gpcon_reg);
-	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
-	__raw_writel(value, gpcon_reg);
-
-	/* Set the external interrupt to pointed trigger type */
-	switch (type)
-	{
-		case IRQT_NOEDGE:
-			printk(KERN_WARNING "No edge setting!\n");
-			break;
-
-		case IRQT_RISING:
-			newvalue = S3C2410_EXTINT_RISEEDGE;
-			break;
-
-		case IRQT_FALLING:
-			newvalue = S3C2410_EXTINT_FALLEDGE;
-			break;
-
-		case IRQT_BOTHEDGE:
-			newvalue = S3C2410_EXTINT_BOTHEDGE;
-			break;
-
-		case IRQT_LOW:
-			newvalue = S3C2410_EXTINT_LOWLEV;
-			break;
-
-		case IRQT_HIGH:
-			newvalue = S3C2410_EXTINT_HILEV;
-			break;
-
-		default:
-			printk(KERN_ERR "No such irq type %d", type);
-			return -1;
-	}
-
-	value = __raw_readl(extint_reg);
-	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
-	__raw_writel(value, extint_reg);
-
-	return 0;
-}
-
-static struct irq_chip s3c_irqext_chip = {
-	.name		= "s3c-ext",
-	.mask		= s3c_irqext_mask,
-	.unmask		= s3c_irqext_unmask,
-	.ack		= s3c_irqext_ack,
-	.set_type	= s3c_irqext_type,
-	.set_wake	= s3c_irqext_wake
-};
-
-static struct irq_chip s3c_irq_eint0t4 = {
-	.name		= "s3c-ext0",
-	.ack		= s3c_irq_ack,
-	.mask		= s3c_irq_mask,
-	.unmask		= s3c_irq_unmask,
-	.set_wake	= s3c_irq_wake,
-	.set_type	= s3c_irqext_type,
-};
-
-/* mask values for the parent registers for each of the interrupt types */
-
-#define INTMSK_UART0	 (1UL << (IRQ_UART0 - IRQ_EINT0))
-#define INTMSK_UART1	 (1UL << (IRQ_UART1 - IRQ_EINT0))
-#define INTMSK_UART2	 (1UL << (IRQ_UART2 - IRQ_EINT0))
-#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
-
-
-/* UART0 */
-
-static void
-s3c_irq_uart0_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
-}
-
-static void
-s3c_irq_uart0_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_UART0);
-}
-
-static void
-s3c_irq_uart0_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
-}
-
-static struct irq_chip s3c_irq_uart0 = {
-	.name		= "s3c-uart0",
-	.mask		= s3c_irq_uart0_mask,
-	.unmask		= s3c_irq_uart0_unmask,
-	.ack		= s3c_irq_uart0_ack,
-};
-
-/* UART1 */
-
-static void
-s3c_irq_uart1_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static void
-s3c_irq_uart1_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_UART1);
-}
-
-static void
-s3c_irq_uart1_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
-}
-
-static struct irq_chip s3c_irq_uart1 = {
-	.name		= "s3c-uart1",
-	.mask		= s3c_irq_uart1_mask,
-	.unmask		= s3c_irq_uart1_unmask,
-	.ack		= s3c_irq_uart1_ack,
-};
-
-/* UART2 */
-
-static void
-s3c_irq_uart2_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static void
-s3c_irq_uart2_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_UART2);
-}
-
-static void
-s3c_irq_uart2_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
-}
-
-static struct irq_chip s3c_irq_uart2 = {
-	.name		= "s3c-uart2",
-	.mask		= s3c_irq_uart2_mask,
-	.unmask		= s3c_irq_uart2_unmask,
-	.ack		= s3c_irq_uart2_ack,
-};
-
-/* ADC and Touchscreen */
-
-static void
-s3c_irq_adc_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static void
-s3c_irq_adc_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
-}
-
-static void
-s3c_irq_adc_ack(unsigned int irqno)
-{
-	s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
-}
-
-static struct irq_chip s3c_irq_adc = {
-	.name		= "s3c-adc",
-	.mask		= s3c_irq_adc_mask,
-	.unmask		= s3c_irq_adc_unmask,
-	.ack		= s3c_irq_adc_ack,
-};
-
-/* irq demux for adc */
-static void s3c_irq_demux_adc(unsigned int irq,
-			      struct irq_desc *desc)
-{
-	unsigned int subsrc, submsk;
-	unsigned int offset = 9;
-	struct irq_desc *mydesc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= offset;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			mydesc = irq_desc + IRQ_TC;
-			desc_handle_irq(IRQ_TC, mydesc);
-		}
-		if (subsrc & 2) {
-			mydesc = irq_desc + IRQ_ADC;
-			desc_handle_irq(IRQ_ADC, mydesc);
-		}
-	}
-}
-
-static void s3c_irq_demux_uart(unsigned int start)
-{
-	unsigned int subsrc, submsk;
-	unsigned int offset = start - IRQ_S3CUART_RX0;
-	struct irq_desc *desc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
-		start, offset, subsrc, submsk);
-
-	subsrc &= ~submsk;
-	subsrc >>= offset;
-	subsrc &= 7;
-
-	if (subsrc != 0) {
-		desc = irq_desc + start;
-
-		if (subsrc & 1)
-			desc_handle_irq(start, desc);
-
-		desc++;
-
-		if (subsrc & 2)
-			desc_handle_irq(start+1, desc);
-
-		desc++;
-
-		if (subsrc & 4)
-			desc_handle_irq(start+2, desc);
-	}
-}
-
-/* uart demux entry points */
-
-static void
-s3c_irq_demux_uart0(unsigned int irq,
-		    struct irq_desc *desc)
-{
-	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX0);
-}
-
-static void
-s3c_irq_demux_uart1(unsigned int irq,
-		    struct irq_desc *desc)
-{
-	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX1);
-}
-
-static void
-s3c_irq_demux_uart2(unsigned int irq,
-		    struct irq_desc *desc)
-{
-	irq = irq;
-	s3c_irq_demux_uart(IRQ_S3CUART_RX2);
-}
-
-static void
-s3c_irq_demux_extint8(unsigned int irq,
-		      struct irq_desc *desc)
-{
-	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
-	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
-	eintpnd &= ~eintmsk;
-	eintpnd &= ~0xff;	/* ignore lower irqs */
-
-	/* we may as well handle all the pending IRQs here */
-
-	while (eintpnd) {
-		irq = __ffs(eintpnd);
-		eintpnd &= ~(1<<irq);
-
-		irq += (IRQ_EINT4 - 4);
-		desc_handle_irq(irq, irq_desc + irq);
-	}
-
-}
-
-static void
-s3c_irq_demux_extint4t7(unsigned int irq,
-			struct irq_desc *desc)
-{
-	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
-	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
-
-	eintpnd &= ~eintmsk;
-	eintpnd &= 0xff;	/* only lower irqs */
-
-	/* we may as well handle all the pending IRQs here */
-
-	while (eintpnd) {
-		irq = __ffs(eintpnd);
-		eintpnd &= ~(1<<irq);
-
-		irq += (IRQ_EINT4 - 4);
-
-		desc_handle_irq(irq, irq_desc + irq);
-	}
-}
-
-#ifdef CONFIG_PM
-
-static struct sleep_save irq_save[] = {
-	SAVE_ITEM(S3C2410_INTMSK),
-	SAVE_ITEM(S3C2410_INTSUBMSK),
-};
-
-/* the extint values move between the s3c2410/s3c2440 and the s3c2412
- * so we use an array to hold them, and to calculate the address of
- * the register at run-time
-*/
-
-static unsigned long save_extint[3];
-static unsigned long save_eintflt[4];
-static unsigned long save_eintmask;
-
-int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-		save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
-
-	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-		save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
-
-	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
-	save_eintmask = __raw_readl(S3C24XX_EINTMASK);
-
-	return 0;
-}
-
-int s3c24xx_irq_resume(struct sys_device *dev)
-{
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
-		__raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
-
-	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
-		__raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
-
-	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
-	__raw_writel(save_eintmask, S3C24XX_EINTMASK);
-
-	return 0;
-}
-
-#else
-#define s3c24xx_irq_suspend NULL
-#define s3c24xx_irq_resume  NULL
-#endif
-
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
-
-void __init s3c24xx_init_irq(void)
-{
-	unsigned long pend;
-	unsigned long last;
-	int irqno;
-	int i;
-
-	irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
-
-	/* first, clear all interrupts pending... */
-
-	last = 0;
-	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C24XX_EINTPEND);
-
-		if (pend == 0 || pend == last)
-			break;
-
-		__raw_writel(pend, S3C24XX_EINTPEND);
-		printk("irq: clearing pending ext status %08x\n", (int)pend);
-		last = pend;
-	}
-
-	last = 0;
-	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C2410_INTPND);
-
-		if (pend == 0 || pend == last)
-			break;
-
-		__raw_writel(pend, S3C2410_SRCPND);
-		__raw_writel(pend, S3C2410_INTPND);
-		printk("irq: clearing pending status %08x\n", (int)pend);
-		last = pend;
-	}
-
-	last = 0;
-	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C2410_SUBSRCPND);
-
-		if (pend == 0 || pend == last)
-			break;
-
-		printk("irq: clearing subpending status %08x\n", (int)pend);
-		__raw_writel(pend, S3C2410_SUBSRCPND);
-		last = pend;
-	}
-
-	/* register the main interrupts */
-
-	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
-
-	for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
-		/* set all the s3c2410 internal irqs */
-
-		switch (irqno) {
-			/* deal with the special IRQs (cascaded) */
-
-		case IRQ_EINT4t7:
-		case IRQ_EINT8t23:
-		case IRQ_UART0:
-		case IRQ_UART1:
-		case IRQ_UART2:
-		case IRQ_ADCPARENT:
-			set_irq_chip(irqno, &s3c_irq_level_chip);
-			set_irq_handler(irqno, handle_level_irq);
-			break;
-
-		case IRQ_RESERVED6:
-		case IRQ_RESERVED24:
-			/* no IRQ here */
-			break;
-
-		default:
-			//irqdbf("registering irq %d (s3c irq)\n", irqno);
-			set_irq_chip(irqno, &s3c_irq_chip);
-			set_irq_handler(irqno, handle_edge_irq);
-			set_irq_flags(irqno, IRQF_VALID);
-		}
-	}
-
-	/* setup the cascade irq handlers */
-
-	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
-	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
-
-	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
-	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
-	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
-
-	/* external interrupts */
-
-	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-		irqdbf("registering irq %d (ext int)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_eint0t4);
-		set_irq_handler(irqno, handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
-		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irqext_chip);
-		set_irq_handler(irqno, handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	/* register the uart interrupts */
-
-	irqdbf("s3c2410: registering external interrupts\n");
-
-	for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
-		irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart0);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
-		irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart1);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
-		irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart2);
-		set_irq_handler(irqno, handle_level_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
-		irqdbf("registering irq %d (s3c adc irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_adc);
-		set_irq_handler(irqno, handle_edge_irq);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
-	irqdbf("s3c2410: registered interrupt handlers\n");
-}
+arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 817e2c6..d54cda1 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-amlm5900.c
  *
  * linux/arch/arm/mach-s3c2410/mach-amlm5900.c
  *
@@ -52,8 +52,8 @@
 #include <asm/arch/regs-lcd.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
 
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index b8b7675..7b81296 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -50,9 +50,9 @@
 
 #include <linux/serial_8250.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 #include "usb-simtec.h"
 
 #define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 15b625e..5af26e1 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -38,10 +38,10 @@
 #include <asm/arch/h1940-latch.h>
 #include <asm/arch/fb.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 static struct map_desc h1940_iodesc[] __initdata = {
 	[0] = {
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 0411e9a..dbac731 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -38,10 +38,10 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/iic.h>
 
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc n30_iodesc[] __initdata = {
 	/* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index 2c738b3..c78ab75 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -32,10 +32,10 @@
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "s3c2410.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc otom11_iodesc[] __initdata = {
   /* Device area */
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 01c0c98..57b8a80 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
  * linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
@@ -49,10 +49,10 @@
 
 #include <asm/arch/regs-serial.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index a382fc0..c947c75 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -43,9 +43,9 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/leds-gpio.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 #include "usb-simtec.h"
 
 /* macros for virtual address mods for the io space entries */
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index ebf294d..3b3a7db 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -1,11 +1,9 @@
 /* linux/arch/arm/mach-s3c2410/pm.c
  *
- * Copyright (c) 2004,2006 Simtec Electronics
+ * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C24XX Power Manager (Suspend-To-RAM) support
- *
- * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,640 +18,139 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Parts based on arch/arm/mach-pxa/pm.c
- *
- * Thanks to Dimitry Andric for debugging
 */
 
 #include <linux/init.h>
 #include <linux/suspend.h>
 #include <linux/errno.h>
 #include <linux/time.h>
-#include <linux/interrupt.h>
-#include <linux/crc32.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
+#include <linux/sysdev.h>
 
-#include <asm/cacheflush.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
+#include <asm/mach-types.h>
+
 #include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-irq.h>
+#include <asm/arch/h1940.h>
 
-#include <asm/mach/time.h>
-
-#include "pm.h"
-
-/* for external use */
-
-unsigned long s3c_pm_flags;
-
-#define PFX "s3c24xx-pm: "
-
-static struct sleep_save core_save[] = {
-	SAVE_ITEM(S3C2410_LOCKTIME),
-	SAVE_ITEM(S3C2410_CLKCON),
-
-	/* we restore the timings here, with the proviso that the board
-	 * brings the system up in an slower, or equal frequency setting
-	 * to the original system.
-	 *
-	 * if we cannot guarantee this, then things are going to go very
-	 * wrong here, as we modify the refresh and both pll settings.
-	 */
-
-	SAVE_ITEM(S3C2410_BWSCON),
-	SAVE_ITEM(S3C2410_BANKCON0),
-	SAVE_ITEM(S3C2410_BANKCON1),
-	SAVE_ITEM(S3C2410_BANKCON2),
-	SAVE_ITEM(S3C2410_BANKCON3),
-	SAVE_ITEM(S3C2410_BANKCON4),
-	SAVE_ITEM(S3C2410_BANKCON5),
-
-	SAVE_ITEM(S3C2410_CLKDIVN),
-	SAVE_ITEM(S3C2410_MPLLCON),
-	SAVE_ITEM(S3C2410_UPLLCON),
-	SAVE_ITEM(S3C2410_CLKSLOW),
-	SAVE_ITEM(S3C2410_REFRESH),
-};
-
-static struct sleep_save gpio_save[] = {
-	SAVE_ITEM(S3C2410_GPACON),
-	SAVE_ITEM(S3C2410_GPADAT),
-
-	SAVE_ITEM(S3C2410_GPBCON),
-	SAVE_ITEM(S3C2410_GPBDAT),
-	SAVE_ITEM(S3C2410_GPBUP),
-
-	SAVE_ITEM(S3C2410_GPCCON),
-	SAVE_ITEM(S3C2410_GPCDAT),
-	SAVE_ITEM(S3C2410_GPCUP),
-
-	SAVE_ITEM(S3C2410_GPDCON),
-	SAVE_ITEM(S3C2410_GPDDAT),
-	SAVE_ITEM(S3C2410_GPDUP),
-
-	SAVE_ITEM(S3C2410_GPECON),
-	SAVE_ITEM(S3C2410_GPEDAT),
-	SAVE_ITEM(S3C2410_GPEUP),
-
-	SAVE_ITEM(S3C2410_GPFCON),
-	SAVE_ITEM(S3C2410_GPFDAT),
-	SAVE_ITEM(S3C2410_GPFUP),
-
-	SAVE_ITEM(S3C2410_GPGCON),
-	SAVE_ITEM(S3C2410_GPGDAT),
-	SAVE_ITEM(S3C2410_GPGUP),
-
-	SAVE_ITEM(S3C2410_GPHCON),
-	SAVE_ITEM(S3C2410_GPHDAT),
-	SAVE_ITEM(S3C2410_GPHUP),
-
-	SAVE_ITEM(S3C2410_DCLKCON),
-};
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 #ifdef CONFIG_S3C2410_PM_DEBUG
-
-#define SAVE_UART(va) \
-	SAVE_ITEM((va) + S3C2410_ULCON), \
-	SAVE_ITEM((va) + S3C2410_UCON), \
-	SAVE_ITEM((va) + S3C2410_UFCON), \
-	SAVE_ITEM((va) + S3C2410_UMCON), \
-	SAVE_ITEM((va) + S3C2410_UBRDIV)
-
-static struct sleep_save uart_save[] = {
-	SAVE_UART(S3C24XX_VA_UART0),
-	SAVE_UART(S3C24XX_VA_UART1),
-#ifndef CONFIG_CPU_S3C2400
-	SAVE_UART(S3C24XX_VA_UART2),
-#endif
-};
-
-/* debug
- *
- * we send the debug to printascii() to allow it to be seen if the
- * system never wakes up from the sleep
-*/
-
-extern void printascii(const char *);
-
-void pm_dbg(const char *fmt, ...)
-{
-	va_list va;
-	char buff[256];
-
-	va_start(va, fmt);
-	vsprintf(buff, fmt, va);
-	va_end(va);
-
-	printascii(buff);
-}
-
-static void s3c2410_pm_debug_init(void)
-{
-	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
-
-	/* re-start uart clocks */
-	tmp |= S3C2410_CLKCON_UART0;
-	tmp |= S3C2410_CLKCON_UART1;
-	tmp |= S3C2410_CLKCON_UART2;
-
-	__raw_writel(tmp, S3C2410_CLKCON);
-	udelay(10);
-}
-
+extern void pm_dbg(const char *fmt, ...);
 #define DBG(fmt...) pm_dbg(fmt)
 #else
 #define DBG(fmt...) printk(KERN_DEBUG fmt)
-
-#define s3c2410_pm_debug_init() do { } while(0)
-
-static struct sleep_save uart_save[] = {};
 #endif
 
-#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
-
-/* suspend checking code...
- *
- * this next area does a set of crc checks over all the installed
- * memory, so the system can verify if the resume was ok.
- *
- * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
- * increasing it will mean that the area corrupted will be less easy to spot,
- * and reducing the size will cause the CRC save area to grow
-*/
-
-#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
-
-static u32 crc_size;	/* size needed for the crc block */
-static u32 *crcs;	/* allocated over suspend/resume */
-
-typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
-
-/* s3c2410_pm_run_res
- *
- * go thorugh the given resource list, and look for system ram
-*/
-
-static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+static void s3c2410_pm_prepare(void)
 {
-	while (ptr != NULL) {
-		if (ptr->child != NULL)
-			s3c2410_pm_run_res(ptr->child, fn, arg);
+	/* ensure at least GSTATUS3 has the resume address */
 
-		if ((ptr->flags & IORESOURCE_MEM) &&
-		    strcmp(ptr->name, "System RAM") == 0) {
-			DBG("Found system RAM at %08lx..%08lx\n",
-			    ptr->start, ptr->end);
-			arg = (fn)(ptr, arg);
-		}
+	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
 
-		ptr = ptr->sibling;
-	}
-}
+	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
 
-static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
-{
-	s3c2410_pm_run_res(&iomem_resource, fn, arg);
-}
+	if (machine_is_h1940()) {
+		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+		unsigned long ptr;
+		unsigned long calc = 0;
 
-static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
-{
-	u32 size = (u32)(res->end - res->start)+1;
+		/* generate check for the bootloader to check on resume */
 
-	size += CHECK_CHUNKSIZE-1;
-	size /= CHECK_CHUNKSIZE;
+		for (ptr = 0; ptr < 0x40000; ptr += 0x400)
+			calc += __raw_readl(base+ptr);
 
-	DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
-
-	*val += size * sizeof(u32);
-	return val;
-}
-
-/* s3c2410_pm_prepare_check
- *
- * prepare the necessary information for creating the CRCs. This
- * must be done before the final save, as it will require memory
- * allocating, and thus touching bits of the kernel we do not
- * know about.
-*/
-
-static void s3c2410_pm_check_prepare(void)
-{
-	crc_size = 0;
-
-	s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
-
-	DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
-
-	crcs = kmalloc(crc_size+4, GFP_KERNEL);
-	if (crcs == NULL)
-		printk(KERN_ERR "Cannot allocated CRC save area\n");
-}
-
-static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
-{
-	unsigned long addr, left;
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		*val = crc32_le(~0, phys_to_virt(addr), left);
-		val++;
+		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
 	}
 
-	return val;
+	/* the RX3715 uses similar code and the same H1940 and the
+	 * same offsets for resume and checksum pointers */
+
+	if (machine_is_rx3715()) {
+		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+		unsigned long ptr;
+		unsigned long calc = 0;
+
+		/* generate check for the bootloader to check on resume */
+
+		for (ptr = 0; ptr < 0x40000; ptr += 0x4)
+			calc += __raw_readl(base+ptr);
+
+		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
+	}
+
+	if ( machine_is_aml_m5900() )
+		s3c2410_gpio_setpin(S3C2410_GPF2, 1);
+
 }
 
-/* s3c2410_pm_check_store
- *
- * compute the CRC values for the memory blocks before the final
- * sleep.
-*/
-
-static void s3c2410_pm_check_store(void)
+static int s3c2410_pm_resume(struct sys_device *dev)
 {
-	if (crcs != NULL)
-		s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
-}
+	unsigned long tmp;
 
-/* in_region
- *
- * return TRUE if the area defined by ptr..ptr+size contatins the
- * what..what+whatsz
-*/
+	/* unset the return-from-sleep flag, to ensure reset */
 
-static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
-{
-	if ((what+whatsz) < ptr)
-		return 0;
+	tmp = __raw_readl(S3C2410_GSTATUS2);
+	tmp &= S3C2410_GSTATUS2_OFFRESET;
+	__raw_writel(tmp, S3C2410_GSTATUS2);
 
-	if (what > (ptr+size))
-		return 0;
-
-	return 1;
-}
-
-static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
-{
-	void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
-	unsigned long addr;
-	unsigned long left;
-	void *ptr;
-	u32 calc;
-
-	for (addr = res->start; addr < res->end;
-	     addr += CHECK_CHUNKSIZE) {
-		left = res->end - addr;
-
-		if (left > CHECK_CHUNKSIZE)
-			left = CHECK_CHUNKSIZE;
-
-		ptr = phys_to_virt(addr);
-
-		if (in_region(ptr, left, crcs, crc_size)) {
-			DBG("skipping %08lx, has crc block in\n", addr);
-			goto skip_check;
-		}
-
-		if (in_region(ptr, left, save_at, 32*4 )) {
-			DBG("skipping %08lx, has save block in\n", addr);
-			goto skip_check;
-		}
-
-		/* calculate and check the checksum */
-
-		calc = crc32_le(~0, ptr, left);
-		if (calc != *val) {
-			printk(KERN_ERR PFX "Restore CRC error at "
-			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
-
-			DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
-			    addr, calc, *val);
-		}
-
-	skip_check:
-		val++;
-	}
-
-	return val;
-}
-
-/* s3c2410_pm_check_restore
- *
- * check the CRCs after the restore event and free the memory used
- * to hold them
-*/
-
-static void s3c2410_pm_check_restore(void)
-{
-	if (crcs != NULL) {
-		s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
-		kfree(crcs);
-		crcs = NULL;
-	}
-}
-
-#else
-
-#define s3c2410_pm_check_prepare() do { } while(0)
-#define s3c2410_pm_check_restore() do { } while(0)
-#define s3c2410_pm_check_store()   do { } while(0)
-#endif
-
-/* helper functions to save and restore register state */
-
-void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		ptr->val = __raw_readl(ptr->reg);
-		DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
-	}
-}
-
-/* s3c2410_pm_do_restore
- *
- * restore the system from the given list of saved registers
- *
- * Note, we do not use DBG() in here, as the system may not have
- * restore the UARTs state yet
-*/
-
-void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
-		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
-
-		__raw_writel(ptr->val, ptr->reg);
-	}
-}
-
-/* s3c2410_pm_do_restore_core
- *
- * similar to s3c2410_pm_do_restore_core
- *
- * WARNING: Do not put any debug in here that may effect memory or use
- * peripherals, as things may be changing!
-*/
-
-static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
-{
-	for (; count > 0; count--, ptr++) {
-		__raw_writel(ptr->val, ptr->reg);
-	}
-}
-
-/* s3c2410_pm_show_resume_irqs
- *
- * print any IRQs asserted at resume time (ie, we woke from)
-*/
-
-static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
-					unsigned long mask)
-{
-	int i;
-
-	which &= ~mask;
-
-	for (i = 0; i <= 31; i++) {
-		if ((which) & (1L<<i)) {
-			DBG("IRQ %d asserted at resume\n", start+i);
-		}
-	}
-}
-
-/* s3c2410_pm_check_resume_pin
- *
- * check to see if the pin is configured correctly for sleep mode, and
- * make any necessary adjustments if it is not
-*/
-
-static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
-{
-	unsigned long irqstate;
-	unsigned long pinstate;
-	int irq = s3c2410_gpio_getirq(pin);
-
-	if (irqoffs < 4)
-		irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
-	else
-		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
-
-	pinstate = s3c2410_gpio_getcfg(pin);
-
-	if (!irqstate) {
-		if (pinstate == S3C2410_GPIO_IRQ)
-			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
-	} else {
-		if (pinstate == S3C2410_GPIO_IRQ) {
-			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
-			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
-		}
-	}
-}
-
-/* s3c2410_pm_configure_extint
- *
- * configure all external interrupt pins
-*/
-
-static void s3c2410_pm_configure_extint(void)
-{
-	int pin;
-
-	/* for each of the external interrupts (EINT0..EINT15) we
-	 * need to check wether it is an external interrupt source,
-	 * and then configure it as an input if it is not
-	*/
-
-	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
-		s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
-	}
-
-	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
-		s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
-	}
-}
-
-void (*pm_cpu_prep)(void);
-void (*pm_cpu_sleep)(void);
-
-#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
-
-/* s3c2410_pm_enter
- *
- * central control for sleep/resume process
-*/
-
-static int s3c2410_pm_enter(suspend_state_t state)
-{
-	unsigned long regs_save[16];
-
-	/* ensure the debug is initialised (if enabled) */
-
-	s3c2410_pm_debug_init();
-
-	DBG("s3c2410_pm_enter(%d)\n", state);
-
-	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
-		printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
-		return -EINVAL;
-	}
-
-	if (state != PM_SUSPEND_MEM) {
-		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
-		return -EINVAL;
-	}
-
-	/* check if we have anything to wake-up with... bad things seem
-	 * to happen if you suspend with no wakeup (system will often
-	 * require a full power-cycle)
-	*/
-
-	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
-	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
-		printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
-		printk(KERN_ERR PFX "Aborting sleep\n");
-		return -EINVAL;
-	}
-
-	/* prepare check area if configured */
-
-	s3c2410_pm_check_prepare();
-
-	/* store the physical address of the register recovery block */
-
-	s3c2410_sleep_save_phys = virt_to_phys(regs_save);
-
-	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
-
-	/* save all necessary core registers not covered by the drivers */
-
-	s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
-	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
-	s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
-
-	/* set the irq configuration for wake */
-
-	s3c2410_pm_configure_extint();
-
-	DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
-	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
-
-	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
-	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
-
-	/* ack any outstanding external interrupts before we go to sleep */
-
-	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
-	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
-	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
-
-	/* call cpu specific preperation */
-
-	pm_cpu_prep();
-
-	/* flush cache back to ram */
-
-	flush_cache_all();
-
-	s3c2410_pm_check_store();
-
-	/* send the cpu to sleep... */
-
-	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
-
-	/* s3c2410_cpu_save will also act as our return point from when
-	 * we resume as it saves its own register state, so use the return
-	 * code to differentiate return from save and return from sleep */
-
-	if (s3c2410_cpu_save(regs_save) == 0) {
-		flush_cache_all();
-		pm_cpu_sleep();
-	}
-
-	/* restore the cpu state */
-
-	cpu_init();
-
-	/* restore the system state */
-
-	s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
-	s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
-	s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
-
-	s3c2410_pm_debug_init();
-
-	/* check what irq (if any) restored the system */
-
-	DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
-	    __raw_readl(S3C2410_SRCPND),
-	    __raw_readl(S3C2410_EINTPEND));
-
-	s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
-				    s3c_irqwake_intmask);
-
-	s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
-				    s3c_irqwake_eintmask);
-
-	DBG("post sleep, preparing to return\n");
-
-	s3c2410_pm_check_restore();
-
-	/* ok, let's return from sleep */
+	if ( machine_is_aml_m5900() )
+		s3c2410_gpio_setpin(S3C2410_GPF2, 0);
 
-	DBG("S3C2410 PM Resume (post-restore)\n");
 	return 0;
 }
 
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int s3c2410_pm_prepare(suspend_state_t state)
+static int s3c2410_pm_add(struct sys_device *dev)
 {
+	pm_cpu_prep = s3c2410_pm_prepare;
+	pm_cpu_sleep = s3c2410_cpu_suspend;
+
 	return 0;
 }
 
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int s3c2410_pm_finish(suspend_state_t state)
-{
-	return 0;
-}
-
-/*
- * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
- */
-static struct pm_ops s3c2410_pm_ops = {
-	.pm_disk_mode	= PM_DISK_FIRMWARE,
-	.prepare	= s3c2410_pm_prepare,
-	.enter		= s3c2410_pm_enter,
-	.finish		= s3c2410_pm_finish,
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
 };
 
-/* s3c2410_pm_init
- *
- * Attach the power management functions. This should be called
- * from the board specific initialisation if the board supports
- * it.
-*/
+/* register ourselves */
 
-int __init s3c2410_pm_init(void)
+static int __init s3c2410_pm_drvinit(void)
 {
-	printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
-
-	pm_set_ops(&s3c2410_pm_ops);
-	return 0;
+	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
 }
+
+arch_initcall(s3c2410_pm_drvinit);
+#endif
+
+#if defined(CONFIG_CPU_S3C2440)
+static struct sysdev_driver s3c2440_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
+};
+
+static int __init s3c2440_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
+}
+
+arch_initcall(s3c2440_pm_drvinit);
+#endif
+
+#if defined(CONFIG_CPU_S3C2442)
+static struct sysdev_driver s3c2442_pm_driver = {
+	.add		= s3c2410_pm_add,
+	.resume		= s3c2410_pm_resume,
+};
+
+static int __init s3c2442_pm_drvinit(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
+}
+
+arch_initcall(s3c2442_pm_drvinit);
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
deleted file mode 100644
index 992cc6a..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-clock.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-clock.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410,S3C2440,S3C2442 Clock control support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/sysdev.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/serial_core.h>
-
-#include <asm/mach/map.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-gpio.h>
-
-#include "s3c2410.h"
-#include "clock.h"
-#include "cpu.h"
-
-int s3c2410_clkcon_enable(struct clk *clk, int enable)
-{
-	unsigned int clocks = clk->ctrlbit;
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2410_CLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	/* ensure none of the special function bits set */
-	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
-
-	__raw_writel(clkcon, S3C2410_CLKCON);
-
-	return 0;
-}
-
-static int s3c2410_upll_enable(struct clk *clk, int enable)
-{
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	unsigned long orig = clkslow;
-
-	if (enable)
-		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
-	else
-		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
-
-	__raw_writel(clkslow, S3C2410_CLKSLOW);
-
-	/* if we started the UPLL, then allow to settle */
-
-	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
-		udelay(200);
-
-	return 0;
-}
-
-/* standard clock definitions */
-
-static struct clk init_clocks_disable[] = {
-	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_NAND,
-	}, {
-		.name		= "sdi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SDI,
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_ADC,
-	}, {
-		.name		= "i2c",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIC,
-	}, {
-		.name		= "iis",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIS,
-	}, {
-		.name		= "spi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SPI,
-	}
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_LCDC,
-	}, {
-		.name		= "gpio",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_GPIO,
-	}, {
-		.name		= "usb-host",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBH,
-	}, {
-		.name		= "usb-device",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBD,
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_PWMT,
-	}, {
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART0,
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART1,
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART2,
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c2410_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_RTC,
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_p,
-		.ctrlbit	= 0,
-	}, {
-		.name		= "usb-bus-host",
-		.id		= -1,
-		.parent		= &clk_usb_bus,
-	}, {
-		.name		= "usb-bus-gadget",
-		.id		= -1,
-		.parent		= &clk_usb_bus,
-	},
-};
-
-/* s3c2410_baseclk_add()
- *
- * Add all the clocks used by the s3c2410 or compatible CPUs
- * such as the S3C2440 and S3C2442.
- *
- * We cannot use a system device as we are needed before any
- * of the init-calls that initialise the devices are actually
- * done.
-*/
-
-int __init s3c2410_baseclk_add(void)
-{
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
-	struct clk *clkp;
-	struct clk *xtal;
-	int ret;
-	int ptr;
-
-	clk_upll.enable = s3c2410_upll_enable;
-
-	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
-		printk(KERN_ERR "failed to register usb bus clock\n");
-
-	/* register clocks from clock array */
-
-	clkp = init_clocks;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		/* ensure that we note the clock state */
-
-		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* We must be careful disabling the clocks we are not intending to
-	 * be using at boot time, as subsytems such as the LCD which do
-	 * their own DMA requests to the bus can cause the system to lockup
-	 * if they where in the middle of requesting bus access.
-	 *
-	 * Disabling the LCD clock if the LCD is active is very dangerous,
-	 * and therefore the bootloader should be careful to not enable
-	 * the LCD clock if it is not needed.
-	*/
-
-	/* install (and disable) the clocks we do not need immediately */
-
-	clkp = init_clocks_disable;
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
-
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-
-		s3c2410_clkcon_enable(clkp, 0);
-	}
-
-	/* show the clock-slow value */
-
-	xtal = clk_get(NULL, "xtal");
-
-	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
-	       print_mhz(clk_get_rate(xtal) /
-			 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
-	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
-	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
-	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
-
-	return 0;
-}
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
deleted file mode 100644
index e67ba39..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-dma.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 DMA selection
- *
- * http://armlinux.simtec.co.uk/
- *
- * 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/init.h>
-#include <linux/sysdev.h>
-#include <linux/serial_core.h>
-
-#include <asm/dma.h>
-#include <asm/arch/dma.h>
-#include "dma.h"
-
-#include "cpu.h"
-
-#include <asm/arch/regs-serial.h>
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-ac97.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-lcd.h>
-#include <asm/arch/regs-sdi.h>
-#include <asm/arch/regs-iis.h>
-#include <asm/arch/regs-spi.h>
-
-static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
-	[DMACH_XD0] = {
-		.name		= "xdreq0",
-		.channels[0]	= S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
-	},
-	[DMACH_XD1] = {
-		.name		= "xdreq1",
-		.channels[1]	= S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
-	},
-	[DMACH_SDI] = {
-		.name		= "sdi",
-		.channels[0]	= S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
-		.channels[3]	= S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_SPI0] = {
-		.name		= "spi0",
-		.channels[1]	= S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + S3C2410_SPRDAT,
-	},
-	[DMACH_SPI1] = {
-		.name		= "spi1",
-		.channels[3]	= S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
-		.hw_addr.from	= S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
-	},
-	[DMACH_UART0] = {
-		.name		= "uart0",
-		.channels[0]	= S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART0 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART0 + S3C2410_URXH,
-	},
-	[DMACH_UART1] = {
-		.name		= "uart1",
-		.channels[1]	= S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART1 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART1 + S3C2410_URXH,
-	},
-      	[DMACH_UART2] = {
-		.name		= "uart2",
-		.channels[3]	= S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_UART2 + S3C2410_UTXH,
-		.hw_addr.from	= S3C2410_PA_UART2 + S3C2410_URXH,
-	},
-	[DMACH_TIMER] = {
-		.name		= "timer",
-		.channels[0]	= S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
-		.channels[3]	= S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
-	},
-	[DMACH_I2S_IN] = {
-		.name		= "i2s-sdi",
-		.channels[1]	= S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
-		.channels[2]	= S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
-		.hw_addr.from	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_I2S_OUT] = {
-		.name		= "i2s-sdo",
-		.channels[2]	= S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
-		.hw_addr.to	= S3C2410_PA_IIS + S3C2410_IISFIFO,
-	},
-	[DMACH_USB_EP1] = {
-		.name		= "usb-ep1",
-		.channels[0]	= S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP2] = {
-		.name		= "usb-ep2",
-		.channels[1]	= S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP3] = {
-		.name		= "usb-ep3",
-		.channels[2]	= S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
-	},
-	[DMACH_USB_EP4] = {
-		.name		= "usb-ep4",
-		.channels[3]	=S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
-	},
-};
-
-static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
-			       struct s3c24xx_dma_map *map)
-{
-	chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
-}
-
-static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
-	.select		= s3c2410_dma_select,
-	.dcon_mask	= 7 << 24,
-	.map		= s3c2410_dma_mappings,
-	.map_size	= ARRAY_SIZE(s3c2410_dma_mappings),
-};
-
-static int s3c2410_dma_add(struct sys_device *sysdev)
-{
-	return s3c24xx_dma_init_map(&s3c2410_dma_sel);
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_dma_driver = {
-	.add	= s3c2410_dma_add,
-};
-
-static int __init s3c2410_dma_init(void)
-{
-	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
-}
-
-arch_initcall(s3c2410_dma_init);
-#endif
-
-#if defined(CONFIG_CPU_S3C2442)
-/* S3C2442 DMA contains the same selection table as the S3C2410 */
-static struct sysdev_driver s3c2442_dma_driver = {
-	.add	= s3c2410_dma_add,
-};
-
-static int __init s3c2442_dma_init(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
-}
-
-arch_initcall(s3c2442_dma_init);
-#endif
-
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
deleted file mode 100644
index ec3a276..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-gpio.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-gpio.c
- *
- * Copyright (c) 2004-2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 GPIO support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#include <asm/arch/regs-gpio.h>
-
-int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-			   unsigned int config)
-{
-	void __iomem *reg = S3C24XX_EINFLT0;
-	unsigned long flags;
-	unsigned long val;
-
-	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
-		return -1;
-
-	config &= 0xff;
-
-	pin -= S3C2410_GPG8;
-	reg += pin & ~3;
-
-	local_irq_save(flags);
-
-	/* update filter width and clock source */
-
-	val = __raw_readl(reg);
-	val &= ~(0xff << ((pin & 3) * 8));
-	val |= config << ((pin & 3) * 8);
-	__raw_writel(val, reg);
-
-	/* update filter enable */
-
-	val = __raw_readl(S3C24XX_EXTINT2);
-	val &= ~(1 << ((pin * 4) + 3));
-	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C24XX_EXTINT2);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c
deleted file mode 100644
index c796c9c..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-irq.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-irq.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/ptrace.h>
-#include <linux/sysdev.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-static int s3c2410_irq_add(struct sys_device *sysdev)
-{
-	return 0;
-}
-
-static struct sysdev_driver s3c2410_irq_driver = {
-	.add		= s3c2410_irq_add,
-	.suspend	= s3c24xx_irq_suspend,
-	.resume		= s3c24xx_irq_resume,
-};
-
-static int s3c2410_irq_init(void)
-{
-	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
-}
-
-arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
deleted file mode 100644
index 8bb6e5e..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-pm.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-pm.c
- *
- * Copyright (c) 2006 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/init.h>
-#include <linux/suspend.h>
-#include <linux/errno.h>
-#include <linux/time.h>
-#include <linux/sysdev.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/h1940.h>
-
-#include "cpu.h"
-#include "pm.h"
-
-#ifdef CONFIG_S3C2410_PM_DEBUG
-extern void pm_dbg(const char *fmt, ...);
-#define DBG(fmt...) pm_dbg(fmt)
-#else
-#define DBG(fmt...) printk(KERN_DEBUG fmt)
-#endif
-
-static void s3c2410_pm_prepare(void)
-{
-	/* ensure at least GSTATUS3 has the resume address */
-
-	__raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
-
-	DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
-	DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
-
-	if (machine_is_h1940()) {
-		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
-		unsigned long ptr;
-		unsigned long calc = 0;
-
-		/* generate check for the bootloader to check on resume */
-
-		for (ptr = 0; ptr < 0x40000; ptr += 0x400)
-			calc += __raw_readl(base+ptr);
-
-		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
-	}
-
-	/* the RX3715 uses similar code and the same H1940 and the
-	 * same offsets for resume and checksum pointers */
-
-	if (machine_is_rx3715()) {
-		void *base = phys_to_virt(H1940_SUSPEND_CHECK);
-		unsigned long ptr;
-		unsigned long calc = 0;
-
-		/* generate check for the bootloader to check on resume */
-
-		for (ptr = 0; ptr < 0x40000; ptr += 0x4)
-			calc += __raw_readl(base+ptr);
-
-		__raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
-	}
-
-	if ( machine_is_aml_m5900() )
-		s3c2410_gpio_setpin(S3C2410_GPF2, 1);
-
-}
-
-static int s3c2410_pm_resume(struct sys_device *dev)
-{
-	unsigned long tmp;
-
-	/* unset the return-from-sleep flag, to ensure reset */
-
-	tmp = __raw_readl(S3C2410_GSTATUS2);
-	tmp &= S3C2410_GSTATUS2_OFFRESET;
-	__raw_writel(tmp, S3C2410_GSTATUS2);
-
-	if ( machine_is_aml_m5900() )
-		s3c2410_gpio_setpin(S3C2410_GPF2, 0);
-
-	return 0;
-}
-
-static int s3c2410_pm_add(struct sys_device *dev)
-{
-	pm_cpu_prep = s3c2410_pm_prepare;
-	pm_cpu_sleep = s3c2410_cpu_suspend;
-
-	return 0;
-}
-
-#if defined(CONFIG_CPU_S3C2410)
-static struct sysdev_driver s3c2410_pm_driver = {
-	.add		= s3c2410_pm_add,
-	.resume		= s3c2410_pm_resume,
-};
-
-/* register ourselves */
-
-static int __init s3c2410_pm_drvinit(void)
-{
-	return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
-}
-
-arch_initcall(s3c2410_pm_drvinit);
-#endif
-
-#if defined(CONFIG_CPU_S3C2440)
-static struct sysdev_driver s3c2440_pm_driver = {
-	.add		= s3c2410_pm_add,
-	.resume		= s3c2410_pm_resume,
-};
-
-static int __init s3c2440_pm_drvinit(void)
-{
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
-}
-
-arch_initcall(s3c2440_pm_drvinit);
-#endif
-
-#if defined(CONFIG_CPU_S3C2442)
-static struct sysdev_driver s3c2442_pm_driver = {
-	.add		= s3c2410_pm_add,
-	.resume		= s3c2410_pm_resume,
-};
-
-static int __init s3c2442_pm_drvinit(void)
-{
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
-}
-
-arch_initcall(s3c2442_pm_drvinit);
-#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S
deleted file mode 100644
index 9179a10..0000000
--- a/arch/arm/mach-s3c2410/s3c2410-sleep.S
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 Power Manager (Suspend-To-RAM) support
- *
- * Based on PXA/SA1100 sleep code by:
- *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
- *	Cliff Brake, (c) 2001
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/hardware.h>
-#include <asm/arch/map.h>
-
-#include <asm/arch/regs-gpio.h>
-#include <asm/arch/regs-clock.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-serial.h>
-
-	/* s3c2410_cpu_suspend
-	 *
-	 * put the cpu into sleep mode
-	*/
-
-ENTRY(s3c2410_cpu_suspend)
-	@@ prepare cpu to sleep
-
-	ldr	r4, =S3C2410_REFRESH
-	ldr	r5, =S3C24XX_MISCCR
-	ldr	r6, =S3C2410_CLKCON
-	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
-	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
-	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
-
-	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
-	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
-	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command
-
-	teq	pc, #0			@ first as a trial-run to load cache
-	bl	s3c2410_do_sleep
-	teq	r0, r0			@ now do it for real
-	b	s3c2410_do_sleep	@
-
-	@@ align next bit of code to cache line
-	.align	8
-s3c2410_do_sleep:
-	streq	r7, [ r4 ]			@ SDRAM sleep command
-	streq	r8, [ r5 ]			@ SDRAM power-down config
-	streq	r9, [ r6 ]			@ CPU sleep
-1:	beq	1b
-	mov	pc, r14
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 4cdc0d7..d96fdcf 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -31,10 +31,10 @@
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-serial.h>
 
-#include "s3c2410.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
 
 /* Initial IO mappings */
 
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 2018c2e..9179a10 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/sleep.S
+/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -34,126 +34,35 @@
 #include <asm/arch/regs-mem.h>
 #include <asm/arch/regs-serial.h>
 
-/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
- * reset the UART configuration, only enable if you really need this!
-*/
-//#define CONFIG_DEBUG_RESUME
-
-	.text
-
-	/* s3c2410_cpu_save
+	/* s3c2410_cpu_suspend
 	 *
-	 * save enough of the CPU state to allow us to re-start
-	 * pm.c code. as we store items like the sp/lr, we will
-	 * end up returning from this function when the cpu resumes
-	 * so the return value is set to mark this.
-	 *
-	 * This arangement means we avoid having to flush the cache
-	 * from this code.
-	 *
-	 * entry:
-	 *	r0 = pointer to save block
-	 *
-	 * exit:
-	 *	r0 = 0 => we stored everything
-	 *	     1 => resumed from sleep
+	 * put the cpu into sleep mode
 	*/
 
-ENTRY(s3c2410_cpu_save)
-	stmfd	sp!, { r4 - r12, lr }
+ENTRY(s3c2410_cpu_suspend)
+	@@ prepare cpu to sleep
 
-	@@ store co-processor registers
+	ldr	r4, =S3C2410_REFRESH
+	ldr	r5, =S3C24XX_MISCCR
+	ldr	r6, =S3C2410_CLKCON
+	ldr	r7, [ r4 ]		@ get REFRESH (and ensure in TLB)
+	ldr	r8, [ r5 ]		@ get MISCCR (and ensure in TLB)
+	ldr	r9, [ r6 ]		@ get CLKCON (and ensure in TLB)
 
-	mrc	p15, 0, r4, c15, c1, 0	@ CP access register
-	mrc	p15, 0, r5, c13, c0, 0	@ PID
-	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r7, c2, c0, 0	@ translation table base address
-	mrc	p15, 0, r8, c1, c0, 0	@ control register
+	orr	r7, r7, #S3C2410_REFRESH_SELF	@ SDRAM sleep command
+	orr	r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
+	orr	r9, r9, #S3C2410_CLKCON_POWER	@ power down command
 
-	stmia	r0, { r4 - r13 }
+	teq	pc, #0			@ first as a trial-run to load cache
+	bl	s3c2410_do_sleep
+	teq	r0, r0			@ now do it for real
+	b	s3c2410_do_sleep	@
 
-	mov	r0, #0
-	ldmfd	sp, { r4 - r12, pc }
-
-	@@ return to the caller, after having the MMU
-	@@ turned on, this restores the last bits from the
-	@@ stack
-resume_with_mmu:
-	mov	r0, #1
-	ldmfd	sp!, { r4 - r12, pc }
-
-	.ltorg
-
-	@@ the next bits sit in the .data segment, even though they
-	@@ happen to be code... the s3c2410_sleep_save_phys needs to be
-	@@ accessed by the resume code before it can restore the MMU.
-	@@ This means that the variable has to be close enough for the
-	@@ code to read it... since the .text segment needs to be RO,
-	@@ the data segment can be the only place to put this code.
-
-	.data
-
-	.global	s3c2410_sleep_save_phys
-s3c2410_sleep_save_phys:
-	.word	0
-
-	/* s3c2410_cpu_resume
-	 *
-	 * resume code entry for bootloader to call
-	 *
-	 * we must put this code here in the data segment as we have no
-	 * other way of restoring the stack pointer after sleep, and we
-	 * must not write to the code segment (code is read-only)
-	*/
-
-ENTRY(s3c2410_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
-	msr	cpsr_c, r0
-
-	@@ load UART to allow us to print the two characters for
-	@@ resume debug
-
-	mov	r2, #S3C24XX_PA_UART & 0xff000000
-	orr	r2, r2, #S3C24XX_PA_UART & 0xff000
-
-#if 0
-	/* SMDK2440 LED set */
-	mov	r14, #S3C24XX_PA_GPIO
-	ldr	r12, [ r14, #0x54 ]
-	bic	r12, r12, #3<<4
-	orr	r12, r12, #1<<7
-	str	r12, [ r14, #0x54 ]
-#endif
-
-#ifdef CONFIG_DEBUG_RESUME
-	mov	r3, #'L'
-	strb	r3, [ r2, #S3C2410_UTXH ]
-1001:
-	ldrb	r14, [ r3, #S3C2410_UTRSTAT ]
-	tst	r14, #S3C2410_UTRSTAT_TXE
-	beq	1001b
-#endif /* CONFIG_DEBUG_RESUME */
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
-
-	ldr	r0, s3c2410_sleep_save_phys	@ address of restore block
-	ldmia	r0, { r4 - r13 }
-
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access register
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr	p15, 0, r6, c3, c0, 0		@ Domain ID
-	mcr	p15, 0, r7, c2, c0, 0		@ translation table base
-
-#ifdef CONFIG_DEBUG_RESUME
-	mov	r3, #'R'
-	strb	r3, [ r2, #S3C2410_UTXH ]
-#endif
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r8, c1, c0, 0		@ turn on MMU, etc
-	nop					@ second-to-last before mmu
-	mov	pc, r2				@ go back to virtual address
-
-	.ltorg
+	@@ align next bit of code to cache line
+	.align	8
+s3c2410_do_sleep:
+	streq	r7, [ r4 ]			@ SDRAM sleep command
+	streq	r8, [ r5 ]			@ SDRAM power-down config
+	streq	r9, [ r6 ]			@ CPU sleep
+1:	beq	1b
+	mov	pc, r14
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 22b0e1c..bcd562a 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -35,7 +35,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "devs.h"
+#include <asm/plat-s3c24xx/devs.h>
 #include "usb-simtec.h"
 
 /* control power and monitor over-current events on various Simtec
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
new file mode 100644
index 0000000..6d629de84
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -0,0 +1,58 @@
+# arch/arm/mach-s3c2412/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2412
+	bool
+	depends on ARCH_S3C2410
+	select S3C2412_PM if PM
+	select S3C2412_DMA if S3C2410_DMA
+	help
+	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
+
+config CPU_S3C2412_ONLY
+	bool
+	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+		   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
+	default y if CPU_S3C2412
+
+config S3C2412_DMA
+	bool
+	depends on CPU_S3C2412
+	help
+	  Internal config node for S3C2412 DMA support
+
+config S3C2412_PM
+	bool
+	help
+	  Internal config node to apply S3C2412 power management
+
+
+menu "S3C2412 Machines"
+
+config MACH_SMDK2413
+	bool "SMDK2413"
+	select CPU_S3C2412
+	select MACH_S3C2413
+	select MACH_SMDK
+	help
+	  Say Y here if you are using an SMDK2413
+
+config MACH_S3C2413
+	bool
+	help
+	  Internal node for S3C2413 version of SMDK2413, so that
+	  machine_is_s3c2413() will work when MACH_SMDK2413 is
+	  selected
+
+config MACH_VSTMS
+	bool "VMSTMS"
+	select CPU_S3C2412
+	help
+	  Say Y here if you are using an VSTMS board
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile
new file mode 100644
index 0000000..f8e0116
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Makefile
@@ -0,0 +1,21 @@
+# arch/arm/mach-s3c2412/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)	+= irq.o
+obj-$(CONFIG_CPU_S3C2412)	+= clock.o
+obj-$(CONFIG_S3C2412_DMA)	+= dma.o
+obj-$(CONFIG_S3C2412_PM)	+= pm.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_SMDK2413)	+= mach-smdk2413.o
+obj-$(CONFIG_MACH_VSTMS)	+= mach-vstms.o
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2412/clock.c
similarity index 98%
rename from arch/arm/mach-s3c2410/s3c2412-clock.c
rename to arch/arm/mach-s3c2412/clock.c
index 8f94ad8..6a8e444 100644
--- a/arch/arm/mach-s3c2410/s3c2412-clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
+/* linux/arch/arm/mach-s3c2412/clock.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -41,9 +41,9 @@
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "s3c2412.h"
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* We currently have to assume that the system is running
  * from the XTPll input, and that all ***REFCLKs are being
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2412/dma.c
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2412-dma.c
rename to arch/arm/mach-s3c2412/dma.c
index 138f726..28b5982 100644
--- a/arch/arm/mach-s3c2410/s3c2412-dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c
+/* linux/arch/arm/mach-s3c2412/dma.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -21,8 +21,8 @@
 #include <asm/arch/dma.h>
 #include <asm/io.h>
 
-#include "dma.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/dma.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2412/irq.c
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2412-irq.c
rename to arch/arm/mach-s3c2412/irq.c
index ffcc30b..e89dbdc 100644
--- a/arch/arm/mach-s3c2410/s3c2412-irq.c
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c
+/* linux/arch/arm/mach-s3c2412/irq.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "cpu.h"
-#include "irq.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/irq.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 /* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
  * having them turn up in both the INT* and the EINT* registers. Whilst
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
similarity index 91%
rename from arch/arm/mach-s3c2410/mach-smdk2413.c
rename to arch/arm/mach-s3c2412/mach-smdk2413.c
index 4f89abd7..32b1561 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
+/* linux/arch/arm/mach-s3c2412/mach-smdk2413.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -39,13 +39,13 @@
 #include <asm/arch/idle.h>
 #include <asm/arch/fb.h>
 
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
 
 static struct map_desc smdk2413_iodesc[] __initdata = {
 };
diff --git a/arch/arm/mach-s3c2410/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
similarity index 93%
rename from arch/arm/mach-s3c2410/mach-vstms.c
rename to arch/arm/mach-s3c2412/mach-vstms.c
index 0360e10..f1afb70 100644
--- a/arch/arm/mach-s3c2410/mach-vstms.c
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-vstms.c
+/* linux/arch/arm/mach-s3c2412/mach-vstms.c
  *
  * (C) 2006 Thomas Gleixner <tglx@linutronix.de>
  *
@@ -43,11 +43,11 @@
 
 #include <asm/arch/nand.h>
 
-#include "s3c2410.h"
-#include "s3c2412.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 
 static struct map_desc vstms_iodesc[] __initdata = {
diff --git a/arch/arm/mach-s3c2410/s3c2412-pm.c b/arch/arm/mach-s3c2412/pm.c
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c2412-pm.c
rename to arch/arm/mach-s3c2412/pm.c
index 19b6332..8988dac 100644
--- a/arch/arm/mach-s3c2410/s3c2412-pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c
+/* linux/arch/arm/mach-s3c2412/pm.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -28,10 +28,10 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
-#include "s3c2412.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
 
 static void s3c2412_cpu_suspend(void)
 {
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c2412.c
rename to arch/arm/mach-s3c2412/s3c2412.c
index 2f651a8..aafe0bc 100644
--- a/arch/arm/mach-s3c2410/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2412.c
+/* linux/arch/arm/mach-s3c2412/s3c2412.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -38,11 +38,11 @@
 #include <asm/arch/regs-gpioj.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "s3c2412.h"
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/s3c2412.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 #ifndef CONFIG_CPU_S3C2412_ONLY
 void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
new file mode 100644
index 0000000..e3bfda0
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -0,0 +1,71 @@
+# arch/arm/mach-s3c2440/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2440
+	bool
+	depends on ARCH_S3C2410
+	select S3C2410_CLOCK
+	select S3C2410_PM if PM
+	select S3C2410_GPIO
+	select S3C2440_DMA if S3C2410_DMA
+	select CPU_S3C244X
+	help
+	  Support for S3C2440 Samsung Mobile CPU based systems.
+
+config S3C2440_DMA
+	bool
+	depends on ARCH_S3C2410 && CPU_S3C24405B
+	help
+	  Support for S3C2440 specific DMA code5A
+
+
+menu "S3C2440 Machines"
+
+config MACH_ANUBIS
+	bool "Simtec Electronics ANUBIS"
+	select CPU_S3C2440
+	select PM_SIMTEC if PM
+	help
+	  Say Y here if you are using the Simtec Electronics ANUBIS
+	  development system
+
+config MACH_OSIRIS
+	bool "Simtec IM2440D20 (OSIRIS) module"
+	select CPU_S3C2440
+	select PM_SIMTEC if PM
+	help
+	  Say Y here if you are using the Simtec IM2440D20 module, also
+	  known as the Osiris.
+
+config MACH_RX3715
+	bool "HP iPAQ rx3715"
+	select CPU_S3C2440
+	select PM_H1940 if PM
+	help
+	  Say Y here if you are using the HP iPAQ rx3715.
+
+config ARCH_S3C2440
+	bool "SMDK2440"
+	select CPU_S3C2440
+	select MACH_SMDK
+	help
+	  Say Y here if you are using the SMDK2440.
+
+config MACH_NEXCODER_2440
+ 	bool "NexVision NEXCODER 2440 Light Board"
+ 	select CPU_S3C2440
+	help
+ 	  Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
+
+config SMDK2440_CPU2440
+	bool "SMDK2440 with S3C2440 CPU module"
+	depends on ARCH_S3C2440
+	default y if ARCH_S3C2440
+	select CPU_S3C2440
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
new file mode 100644
index 0000000..c81ed62
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -0,0 +1,23 @@
+# arch/arm/mach-s3c2440/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o dsc.o
+obj-$(CONFIG_CPU_S3C2440)	+= irq.o
+obj-$(CONFIG_CPU_S3C2440)	+= clock.o
+obj-$(CONFIG_S3C2440_DMA)	+= dma.o
+
+# Machine support
+
+obj-$(CONFIG_MACH_ANUBIS)	+= mach-anubis.o
+obj-$(CONFIG_MACH_OSIRIS)	+= mach-osiris.o
+obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
+obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
+obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2440/clock.c
similarity index 96%
rename from arch/arm/mach-s3c2410/s3c2440-clock.c
rename to arch/arm/mach-s3c2440/clock.c
index ba13c1d..79e2ea4 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c
+/* linux/arch/arm/mach-s3c2440/clock.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
 
 #include <asm/arch/regs-clock.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* S3C2440 extended clock support */
 
diff --git a/arch/arm/mach-s3c2410/s3c2440-dma.c b/arch/arm/mach-s3c2440/dma.c
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2440-dma.c
rename to arch/arm/mach-s3c2440/dma.c
index 47b861b..8e51137 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c
+/* linux/arch/arm/mach-s3c2440/dma.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -19,9 +19,9 @@
 
 #include <asm/dma.h>
 #include <asm/arch/dma.h>
-#include "dma.h"
+#include <asm/plat-s3c24xx/dma.h>
 
-#include "cpu.h"
+#include <asm/plat-s3c24xx/cpu.h>
 
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2440/dsc.c
similarity index 90%
rename from arch/arm/mach-s3c2410/s3c2440-dsc.c
rename to arch/arm/mach-s3c2440/dsc.c
index c92ea66..2995ff5 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dsc.c
+++ b/arch/arm/mach-s3c2440/dsc.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c
+/* linux/arch/arm/mach-s3c2440/dsc.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
@@ -27,8 +27,8 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "cpu.h"
-#include "s3c2440.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
 
 int s3c2440_set_dsc(unsigned int pin, unsigned int value)
 {
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2440/irq.c
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2440-irq.c
rename to arch/arm/mach-s3c2440/irq.c
index 1ba19b2..1069d13 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2440/irq.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
+/* linux/arch/arm/mach-s3c2440/irq.c
  *
  * Copyright (c) 2003,2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
 
 /* WDT/AC97 */
 
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
similarity index 97%
rename from arch/arm/mach-s3c2410/mach-anubis.c
rename to arch/arm/mach-s3c2440/mach-anubis.c
index 0fad0c2..3f0288e 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-anubis.c
+/* linux/arch/arm/mach-s3c2440/mach-anubis.c
  *
  * Copyright (c) 2003-2005 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
@@ -42,9 +42,9 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 #define COPYRIGHT ", (c) 2005 Simtec Electronics"
 
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
similarity index 94%
rename from arch/arm/mach-s3c2410/mach-nexcoder.c
rename to arch/arm/mach-s3c2440/mach-nexcoder.c
index d6dfdad..6d551d8 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-nexcoder.c
+/* linux/arch/arm/mach-s3c2440/mach-nexcoder.c
  *
  * Copyright (c) 2004 Nex Vision
  *   Guillaume GOURAT <guillaume.gourat@nexvision.tv>
@@ -38,11 +38,11 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-serial.h>
 
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct map_desc nexcoder_iodesc[] __initdata = {
 	/* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
similarity index 97%
rename from arch/arm/mach-s3c2410/mach-osiris.c
rename to arch/arm/mach-s3c2440/mach-osiris.c
index 37b4085..2ed8e51 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-osiris.c
+/* linux/arch/arm/mach-s3c2440/mach-osiris.c
  *
  * Copyright (c) 2005 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
@@ -41,9 +41,9 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* onboard perihpheral map */
 
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
similarity index 96%
rename from arch/arm/mach-s3c2410/mach-rx3715.c
rename to arch/arm/mach-s3c2440/mach-rx3715.c
index ecbcdf7..1d4e19b 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-rx3715.c
+/* linux/arch/arm/mach-s3c2440/mach-rx3715.c
  *
  * Copyright (c) 2003,2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -46,10 +46,10 @@
 #include <asm/arch/nand.h>
 #include <asm/arch/fb.h>
 
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 static struct map_desc rx3715_iodesc[] __initdata = {
 	/* dump ISA space somewhere unused */
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
similarity index 94%
rename from arch/arm/mach-s3c2410/mach-smdk2440.c
rename to arch/arm/mach-s3c2440/mach-smdk2440.c
index 2b61f4e..270e42b 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/mach-smdk2440.c
+/* linux/arch/arm/mach-s3c2440/mach-smdk2440.c
  *
  * Copyright (c) 2004,2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -40,13 +40,13 @@
 #include <asm/arch/idle.h>
 #include <asm/arch/fb.h>
 
-#include "s3c2410.h"
-#include "s3c2440.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-#include "common-smdk.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
 
 static struct map_desc smdk2440_iodesc[] __initdata = {
 	/* ISA IO Space map (memory space selected by A24) */
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
similarity index 88%
rename from arch/arm/mach-s3c2410/s3c2440.c
rename to arch/arm/mach-s3c2440/s3c2440.c
index 344eb27..90e1da6 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2440/s3c2440.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2440.c
+/* linux/arch/arm/mach-s3c2440/s3c2440.c
  *
  * Copyright (c) 2004-2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
@@ -29,9 +29,9 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "s3c2440.h"
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct sys_device s3c2440_sysdev = {
 	.cls		= &s3c2440_sysclass,
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
new file mode 100644
index 0000000..bf8d87a
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Kconfig
@@ -0,0 +1,27 @@
+# arch/arm/mach-s3c2442/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config CPU_S3C2442
+	bool
+	depends on ARCH_S3C2420
+	select S3C2410_CLOCK
+	select S3C2410_GPIO
+	select S3C2410_PM if PM
+	select CPU_S3C244X
+	help
+	  Support for S3C2442 Samsung Mobile CPU based systems.
+
+
+menu "S3C2442 Machines"
+
+config SMDK2440_CPU2442
+	bool "SMDM2440 with S3C2442 CPU module"
+	depends on ARCH_S3C2440
+	select CPU_S3C2442
+
+
+endmenu
+
diff --git a/arch/arm/mach-s3c2442/Makefile b/arch/arm/mach-s3c2442/Makefile
new file mode 100644
index 0000000..2a909c6
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Makefile
@@ -0,0 +1,16 @@
+# arch/arm/mach-s3c2442/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
+obj-$(CONFIG_CPU_S3C2442)	+= clock.o
+
+# Machine support
+
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2442/clock.c
similarity index 96%
rename from arch/arm/mach-s3c2410/s3c2442-clock.c
rename to arch/arm/mach-s3c2442/clock.c
index 4e292ca..5b9e830 100644
--- a/arch/arm/mach-s3c2410/s3c2442-clock.c
+++ b/arch/arm/mach-s3c2442/clock.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
+/* linux/arch/arm/mach-s3c2442/clock.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
 
 #include <asm/arch/regs-clock.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* S3C2442 extended clock support */
 
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2442/s3c2442.c
similarity index 86%
rename from arch/arm/mach-s3c2410/s3c2442.c
rename to arch/arm/mach-s3c2442/s3c2442.c
index 428732e..fbf8264 100644
--- a/arch/arm/mach-s3c2410/s3c2442.c
+++ b/arch/arm/mach-s3c2442/s3c2442.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c2442.c
+/* linux/arch/arm/mach-s3c2442/s3c2442.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
@@ -19,8 +19,8 @@
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
 
-#include "s3c2442.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/s3c2442.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static struct sys_device s3c2442_sysdev = {
 	.cls		= &s3c2442_sysclass,
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
new file mode 100644
index 0000000..9781364
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -0,0 +1,96 @@
+# arch/arm/plat-s3c24xx/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+config PLAT_S3C24XX
+	bool
+	depends on ARCH_S3C2410
+	default y
+	help
+	  Base platform code for any Samsung S3C device
+
+config CPU_S3C244X
+	bool
+	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+	help
+	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
+config PM_SIMTEC
+	bool
+	help
+	  Common power management code for systems that are
+	  compatible with the Simtec style of power management
+
+config S3C2410_BOOT_WATCHDOG
+	bool "S3C2410 Initialisation watchdog"
+	depends on ARCH_S3C2410 && S3C2410_WATCHDOG
+	help
+	  Say y to enable the watchdog during the kernel decompression
+	  stage. If the kernel fails to uncompress, then the watchdog
+	  will trigger a reset and the system should restart.
+
+config S3C2410_BOOT_ERROR_RESET
+	bool "S3C2410 Reboot on decompression error"
+	depends on ARCH_S3C2410
+	help
+	  Say y here to use the watchdog to reset the system if the
+	  kernel decompressor detects an error during decompression.
+
+config S3C2410_PM_DEBUG
+	bool "S3C2410 PM Suspend debug"
+	depends on ARCH_S3C2410 && PM
+	help
+	  Say Y here if you want verbose debugging from the PM Suspend and
+	  Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
+	  for more information.
+
+config S3C2410_PM_CHECK
+	bool "S3C2410 PM Suspend Memory CRC"
+	depends on ARCH_S3C2410 && PM && CRC32
+	help
+ 	  Enable the PM code's memory area checksum over sleep. This option
+	  will generate CRCs of all blocks of memory, and store them before
+	  going to sleep. The blocks are then checked on resume for any
+	  errors.
+
+config S3C2410_PM_CHECK_CHUNKSIZE
+	int "S3C2410 PM Suspend CRC Chunksize (KiB)"
+	depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
+	default 64
+	help
+	  Set the chunksize in Kilobytes of the CRC for checking memory
+	  corruption over suspend and resume. A smaller value will mean that
+	  the CRC data block will take more memory, but wil identify any
+	  faults with better precision.
+
+config S3C2410_LOWLEVEL_UART_PORT
+	int "S3C2410 UART to use for low-level messages"
+	default 0
+	help
+	  Choice of which UART port to use for the low-level messages,
+	  such as the `Uncompressing...` at start time. The value of
+	  this configuration should be between zero and two. The port
+	  must have been initialised by the boot-loader before use.
+
+config S3C2410_DMA
+	bool "S3C2410 DMA support"
+	depends on ARCH_S3C2410
+	help
+	  S3C2410 DMA support. This is needed for drivers like sound which
+	  use the S3C2410's DMA system to move data to and from the
+	  peripheral blocks.
+
+config S3C2410_DMA_DEBUG
+	bool "S3C2410 DMA support debug"
+	depends on ARCH_S3C2410 && S3C2410_DMA
+	help
+	  Enable debugging output for the DMA code. This option sends info
+	  to the kernel log, at priority KERN_DEBUG.
+
+config MACH_SMDK
+	bool
+	help
+	  Common machine code for SMDK2410 and SMDK2440
+
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
new file mode 100644
index 0000000..8e5ccaa
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -0,0 +1,30 @@
+# arch/arm/plat-s3c24xx/Makefile
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+
+# Core files
+
+obj-y				+= cpu.o
+obj-y				+= irq.o
+obj-y				+= devs.o
+obj-y				+= gpio.o
+obj-y				+= time.o
+obj-y				+= clock.o
+
+# Architecture dependant builds
+
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-irq.o
+obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
+obj-$(CONFIG_PM)		+= pm.o
+obj-$(CONFIG_PM)		+= sleep.o
+obj-$(CONFIG_S3C2410_DMA)	+= dma.o
+obj-$(CONFIG_MACH_SMDK)		+= common-smdk.o
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
new file mode 100644
index 0000000..d3dc03a
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/clock.c
@@ -0,0 +1,449 @@
+/* linux/arch/arm/plat-s3c24xx/clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Core clock control support
+ *
+ * Based on, and code from linux/arch/arm/mach-versatile/clock.c
+ **
+ **  Copyright (C) 2004 ARM Limited.
+ **  Written by Deep Blue Solutions Limited.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
+
+/* clock information */
+
+static LIST_HEAD(clocks);
+
+DEFINE_MUTEX(clocks_mutex);
+
+/* enable and disable calls for use with the clk struct */
+
+static int clk_null_enable(struct clk *clk, int enable)
+{
+	return 0;
+}
+
+/* Clock API calls */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p;
+	struct clk *clk = ERR_PTR(-ENOENT);
+	int idno;
+
+	if (dev == NULL || dev->bus != &platform_bus_type)
+		idno = -1;
+	else
+		idno = to_platform_device(dev)->id;
+
+	mutex_lock(&clocks_mutex);
+
+	list_for_each_entry(p, &clocks, list) {
+		if (p->id == idno &&
+		    strcmp(id, p->name) == 0 &&
+		    try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+
+	/* check for the case where a device was supplied, but the
+	 * clock that was being searched for is not device specific */
+
+	if (IS_ERR(clk)) {
+		list_for_each_entry(p, &clocks, list) {
+			if (p->id == -1 && strcmp(id, p->name) == 0 &&
+			    try_module_get(p->owner)) {
+				clk = p;
+				break;
+			}
+		}
+	}
+
+	mutex_unlock(&clocks_mutex);
+	return clk;
+}
+
+void clk_put(struct clk *clk)
+{
+	module_put(clk->owner);
+}
+
+int clk_enable(struct clk *clk)
+{
+	if (IS_ERR(clk) || clk == NULL)
+		return -EINVAL;
+
+	clk_enable(clk->parent);
+
+	mutex_lock(&clocks_mutex);
+
+	if ((clk->usage++) == 0)
+		(clk->enable)(clk, 1);
+
+	mutex_unlock(&clocks_mutex);
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	if (IS_ERR(clk) || clk == NULL)
+		return;
+
+	mutex_lock(&clocks_mutex);
+
+	if ((--clk->usage) == 0)
+		(clk->enable)(clk, 0);
+
+	mutex_unlock(&clocks_mutex);
+	clk_disable(clk->parent);
+}
+
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (IS_ERR(clk))
+		return 0;
+
+	if (clk->rate != 0)
+		return clk->rate;
+
+	if (clk->get_rate != NULL)
+		return (clk->get_rate)(clk);
+
+	if (clk->parent != NULL)
+		return clk_get_rate(clk->parent);
+
+	return clk->rate;
+}
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (!IS_ERR(clk) && clk->round_rate)
+		return (clk->round_rate)(clk, rate);
+
+	return rate;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret;
+
+	if (IS_ERR(clk))
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+	ret = (clk->set_rate)(clk, rate);
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = 0;
+
+	if (IS_ERR(clk))
+		return -EINVAL;
+
+	mutex_lock(&clocks_mutex);
+
+	if (clk->set_parent)
+		ret = (clk->set_parent)(clk, parent);
+
+	mutex_unlock(&clocks_mutex);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_get);
+EXPORT_SYMBOL(clk_put);
+EXPORT_SYMBOL(clk_enable);
+EXPORT_SYMBOL(clk_disable);
+EXPORT_SYMBOL(clk_get_rate);
+EXPORT_SYMBOL(clk_round_rate);
+EXPORT_SYMBOL(clk_set_rate);
+EXPORT_SYMBOL(clk_get_parent);
+EXPORT_SYMBOL(clk_set_parent);
+
+/* base clocks */
+
+struct clk clk_xtal = {
+	.name		= "xtal",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_mpll = {
+	.name		= "mpll",
+	.id		= -1,
+};
+
+struct clk clk_upll = {
+	.name		= "upll",
+	.id		= -1,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_f = {
+	.name		= "fclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= &clk_mpll,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_h = {
+	.name		= "hclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_p = {
+	.name		= "pclk",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
+struct clk clk_usb_bus = {
+	.name		= "usb-bus",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= &clk_upll,
+};
+
+/* clocks that could be registered by external code */
+
+static int s3c24xx_dclk_enable(struct clk *clk, int enable)
+{
+	unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+	if (enable)
+		dclkcon |= clk->ctrlbit;
+	else
+		dclkcon &= ~clk->ctrlbit;
+
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+	return 0;
+}
+
+static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
+{
+	unsigned long dclkcon;
+	unsigned int uclk;
+
+	if (parent == &clk_upll)
+		uclk = 1;
+	else if (parent == &clk_p)
+		uclk = 0;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	dclkcon = __raw_readl(S3C24XX_DCLKCON);
+
+	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
+		if (uclk)
+			dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
+		else
+			dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
+	} else {
+		if (uclk)
+			dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
+		else
+			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
+	}
+
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
+
+	return 0;
+}
+
+
+static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
+{
+	unsigned long mask;
+	unsigned long source;
+
+	/* calculate the MISCCR setting for the clock */
+
+	if (parent == &clk_xtal)
+		source = S3C2410_MISCCR_CLK0_MPLL;
+	else if (parent == &clk_upll)
+		source = S3C2410_MISCCR_CLK0_UPLL;
+	else if (parent == &clk_f)
+		source = S3C2410_MISCCR_CLK0_FCLK;
+	else if (parent == &clk_h)
+		source = S3C2410_MISCCR_CLK0_HCLK;
+	else if (parent == &clk_p)
+		source = S3C2410_MISCCR_CLK0_PCLK;
+	else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
+		source = S3C2410_MISCCR_CLK0_DCLK0;
+	else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
+		source = S3C2410_MISCCR_CLK0_DCLK0;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	if (clk == &s3c24xx_dclk0)
+		mask = S3C2410_MISCCR_CLK0_MASK;
+	else {
+		source <<= 4;
+		mask = S3C2410_MISCCR_CLK1_MASK;
+	}
+
+	s3c2410_modify_misccr(mask, source);
+	return 0;
+}
+
+/* external clock definitions */
+
+struct clk s3c24xx_dclk0 = {
+	.name		= "dclk0",
+	.id		= -1,
+	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
+	.enable	        = s3c24xx_dclk_enable,
+	.set_parent	= s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_dclk1 = {
+	.name		= "dclk1",
+	.id		= -1,
+	.ctrlbit	= S3C2410_DCLKCON_DCLK0EN,
+	.enable		= s3c24xx_dclk_enable,
+	.set_parent	= s3c24xx_dclk_setparent,
+};
+
+struct clk s3c24xx_clkout0 = {
+	.name		= "clkout0",
+	.id		= -1,
+	.set_parent	= s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_clkout1 = {
+	.name		= "clkout1",
+	.id		= -1,
+	.set_parent	= s3c24xx_clkout_setparent,
+};
+
+struct clk s3c24xx_uclk = {
+	.name		= "uclk",
+	.id		= -1,
+};
+
+/* initialise the clock system */
+
+int s3c24xx_register_clock(struct clk *clk)
+{
+	clk->owner = THIS_MODULE;
+
+	if (clk->enable == NULL)
+		clk->enable = clk_null_enable;
+
+	/* add to the list of available clocks */
+
+	mutex_lock(&clocks_mutex);
+	list_add(&clk->list, &clocks);
+	mutex_unlock(&clocks_mutex);
+
+	return 0;
+}
+
+/* initalise all the clocks */
+
+int __init s3c24xx_setup_clocks(unsigned long xtal,
+				unsigned long fclk,
+				unsigned long hclk,
+				unsigned long pclk)
+{
+	printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
+
+	/* initialise the main system clocks */
+
+	clk_xtal.rate = xtal;
+	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
+
+	clk_mpll.rate = fclk;
+	clk_h.rate = hclk;
+	clk_p.rate = pclk;
+	clk_f.rate = fclk;
+
+	/* assume uart clocks are correctly setup */
+
+	/* register our clocks */
+
+	if (s3c24xx_register_clock(&clk_xtal) < 0)
+		printk(KERN_ERR "failed to register master xtal\n");
+
+	if (s3c24xx_register_clock(&clk_mpll) < 0)
+		printk(KERN_ERR "failed to register mpll clock\n");
+
+	if (s3c24xx_register_clock(&clk_upll) < 0)
+		printk(KERN_ERR "failed to register upll clock\n");
+
+	if (s3c24xx_register_clock(&clk_f) < 0)
+		printk(KERN_ERR "failed to register cpu fclk\n");
+
+	if (s3c24xx_register_clock(&clk_h) < 0)
+		printk(KERN_ERR "failed to register cpu hclk\n");
+
+	if (s3c24xx_register_clock(&clk_p) < 0)
+		printk(KERN_ERR "failed to register cpu pclk\n");
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
similarity index 96%
rename from arch/arm/mach-s3c2410/common-smdk.c
rename to arch/arm/plat-s3c24xx/common-smdk.c
index a40eaa6..908efa7 100644
--- a/arch/arm/mach-s3c2410/common-smdk.c
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/common-smdk.c
+/* linux/arch/arm/plat-s3c24xx/common-smdk.c
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -38,9 +38,9 @@
 
 #include <asm/arch/nand.h>
 
-#include "common-smdk.h"
-#include "devs.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/common-smdk.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 /* LED devices */
 
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
similarity index 95%
rename from arch/arm/mach-s3c2410/cpu.c
rename to arch/arm/plat-s3c24xx/cpu.c
index ae1f5bb..2fbb749 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/cpu.c
+/* linux/arch/arm/plat-s3c24xx/cpu.c
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	http://www.simtec.co.uk/products/SWLINUX/
@@ -40,15 +40,15 @@
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-serial.h>
 
-#include "cpu.h"
-#include "devs.h"
-#include "clock.h"
-#include "s3c2400.h"
-#include "s3c2410.h"
-#include "s3c2412.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/s3c2400.h>
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2412.h>
 #include "s3c244x.h"
-#include "s3c2440.h"
-#include "s3c2442.h"
+#include <asm/plat-s3c24xx/s3c2440.h>
+#include <asm/plat-s3c24xx/s3c2442.h>
 
 struct cpu_table {
 	unsigned long	idcode;
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/plat-s3c24xx/devs.c
similarity index 98%
rename from arch/arm/mach-s3c2410/devs.c
rename to arch/arm/plat-s3c24xx/devs.c
index faccde2..6d46c4e 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/devs.c
+/* linux/arch/arm/plat-s3c24xx/devs.c
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -30,8 +30,8 @@
 
 #include <asm/arch/regs-serial.h>
 
-#include "devs.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 /* Serial port registrations */
 
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
new file mode 100644
index 0000000..c784e1f
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -0,0 +1,1441 @@
+/* linux/arch/arm/plat-s3c24xx/dma.c
+ *
+ * Copyright (c) 2003-2005,2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 DMA core
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * 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.
+*/
+
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/sysdev.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <asm/mach/dma.h>
+#include <asm/arch/map.h>
+
+#include <asm/plat-s3c24xx/dma.h>
+
+/* io map for dma */
+static void __iomem *dma_base;
+static struct kmem_cache *dma_kmem;
+
+struct s3c24xx_dma_selection dma_sel;
+
+/* dma channel state information */
+struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
+
+/* debugging functions */
+
+#define BUF_MAGIC (0xcafebabe)
+
+#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
+
+#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
+
+#if 1
+#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
+#else
+static inline void
+dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
+{
+	pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
+	writel(val, dma_regaddr(chan, reg));
+}
+#endif
+
+#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
+
+/* captured register state for debug */
+
+struct s3c2410_dma_regstate {
+	unsigned long         dcsrc;
+	unsigned long         disrc;
+	unsigned long         dstat;
+	unsigned long         dcon;
+	unsigned long         dmsktrig;
+};
+
+#ifdef CONFIG_S3C2410_DMA_DEBUG
+
+/* dmadbg_showregs
+ *
+ * simple debug routine to print the current state of the dma registers
+*/
+
+static void
+dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
+{
+	regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+	regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
+	regs->dstat    = dma_rdreg(chan, S3C2410_DMA_DSTAT);
+	regs->dcon     = dma_rdreg(chan, S3C2410_DMA_DCON);
+	regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+}
+
+static void
+dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
+		 struct s3c2410_dma_regstate *regs)
+{
+	printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
+	       chan->number, fname, line,
+	       regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
+	       regs->dcon);
+}
+
+static void
+dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_regstate state;
+
+	dmadbg_capture(chan, &state);
+
+	printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
+	       chan->number, fname, line, chan->load_state,
+	       chan->curr, chan->next, chan->end);
+
+	dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_regstate state;
+
+	dmadbg_capture(chan, &state);
+	dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
+#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
+#else
+#define dbg_showregs(chan) do { } while(0)
+#define dbg_showchan(chan) do { } while(0)
+#endif /* CONFIG_S3C2410_DMA_DEBUG */
+
+static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
+
+/* lookup_dma_channel
+ *
+ * change the dma channel number given into a real dma channel id
+*/
+
+static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
+{
+	if (channel & DMACH_LOW_LEVEL)
+		return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
+	else
+		return dma_chan_map[channel];
+}
+
+/* s3c2410_dma_stats_timeout
+ *
+ * Update DMA stats from timeout info
+*/
+
+static void
+s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
+{
+	if (stats == NULL)
+		return;
+
+	if (val > stats->timeout_longest)
+		stats->timeout_longest = val;
+	if (val < stats->timeout_shortest)
+		stats->timeout_shortest = val;
+
+	stats->timeout_avg += val;
+}
+
+/* s3c2410_dma_waitforload
+ *
+ * wait for the DMA engine to load a buffer, and update the state accordingly
+*/
+
+static int
+s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
+{
+	int timeout = chan->load_timeout;
+	int took;
+
+	if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
+		printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
+		return 0;
+	}
+
+	if (chan->stats != NULL)
+		chan->stats->loads++;
+
+	while (--timeout > 0) {
+		if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
+			took = chan->load_timeout - timeout;
+
+			s3c2410_dma_stats_timeout(chan->stats, took);
+
+			switch (chan->load_state) {
+			case S3C2410_DMALOAD_1LOADED:
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				break;
+
+			default:
+				printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
+			}
+
+			return 1;
+		}
+	}
+
+	if (chan->stats != NULL) {
+		chan->stats->timeout_failed++;
+	}
+
+	return 0;
+}
+
+
+
+/* s3c2410_dma_loadbuffer
+ *
+ * load a buffer, and update the channel state
+*/
+
+static inline int
+s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
+		       struct s3c2410_dma_buf *buf)
+{
+	unsigned long reload;
+
+	pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
+		 buf, (unsigned long)buf->data, buf->size);
+
+	if (buf == NULL) {
+		dmawarn("buffer is NULL\n");
+		return -EINVAL;
+	}
+
+	/* check the state of the channel before we do anything */
+
+	if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+		dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
+	}
+
+	if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
+		dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
+	}
+
+	/* it would seem sensible if we are the last buffer to not bother
+	 * with the auto-reload bit, so that the DMA engine will not try
+	 * and load another transfer after this one has finished...
+	 */
+	if (chan->load_state == S3C2410_DMALOAD_NONE) {
+		pr_debug("load_state is none, checking for noreload (next=%p)\n",
+			 buf->next);
+		reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
+	} else {
+		//pr_debug("load_state is %d => autoreload\n", chan->load_state);
+		reload = S3C2410_DCON_AUTORELOAD;
+	}
+
+	if ((buf->data & 0xf0000000) != 0x30000000) {
+		dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
+	}
+
+	writel(buf->data, chan->addr_reg);
+
+	dma_wrreg(chan, S3C2410_DMA_DCON,
+		  chan->dcon | reload | (buf->size/chan->xfer_unit));
+
+	chan->next = buf->next;
+
+	/* update the state of the channel */
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_NONE:
+		chan->load_state = S3C2410_DMALOAD_1LOADED;
+		break;
+
+	case S3C2410_DMALOAD_1RUNNING:
+		chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
+		break;
+
+	default:
+		dmawarn("dmaload: unknown state %d in loadbuffer\n",
+			chan->load_state);
+		break;
+	}
+
+	return 0;
+}
+
+/* s3c2410_dma_call_op
+ *
+ * small routine to call the op routine with the given op if it has been
+ * registered
+*/
+
+static void
+s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
+{
+	if (chan->op_fn != NULL) {
+		(chan->op_fn)(chan, op);
+	}
+}
+
+/* s3c2410_dma_buffdone
+ *
+ * small wrapper to check if callback routine needs to be called, and
+ * if so, call it
+*/
+
+static inline void
+s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
+		     enum s3c2410_dma_buffresult result)
+{
+#if 0
+	pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
+		 chan->callback_fn, buf, buf->id, buf->size, result);
+#endif
+
+	if (chan->callback_fn != NULL) {
+		(chan->callback_fn)(chan, buf->id, buf->size, result);
+	}
+}
+
+/* s3c2410_dma_start
+ *
+ * start a dma channel going
+*/
+
+static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
+{
+	unsigned long tmp;
+	unsigned long flags;
+
+	pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
+
+	local_irq_save(flags);
+
+	if (chan->state == S3C2410_DMA_RUNNING) {
+		pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
+		local_irq_restore(flags);
+		return 0;
+	}
+
+	chan->state = S3C2410_DMA_RUNNING;
+
+	/* check wether there is anything to load, and if not, see
+	 * if we can find anything to load
+	 */
+
+	if (chan->load_state == S3C2410_DMALOAD_NONE) {
+		if (chan->next == NULL) {
+			printk(KERN_ERR "dma%d: channel has nothing loaded\n",
+			       chan->number);
+			chan->state = S3C2410_DMA_IDLE;
+			local_irq_restore(flags);
+			return -EINVAL;
+		}
+
+		s3c2410_dma_loadbuffer(chan, chan->next);
+	}
+
+	dbg_showchan(chan);
+
+	/* enable the channel */
+
+	if (!chan->irq_enabled) {
+		enable_irq(chan->irq);
+		chan->irq_enabled = 1;
+	}
+
+	/* start the channel going */
+
+	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	tmp &= ~S3C2410_DMASKTRIG_STOP;
+	tmp |= S3C2410_DMASKTRIG_ON;
+	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+	pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
+
+#if 0
+	/* the dma buffer loads should take care of clearing the AUTO
+	 * reloading feature */
+	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+	tmp &= ~S3C2410_DCON_NORELOAD;
+	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+	s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
+
+	dbg_showchan(chan);
+
+	/* if we've only loaded one buffer onto the channel, then chec
+	 * to see if we have another, and if so, try and load it so when
+	 * the first buffer is finished, the new one will be loaded onto
+	 * the channel */
+
+	if (chan->next != NULL) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				pr_debug("%s: buff not yet loaded, no more todo\n",
+					 __FUNCTION__);
+			} else {
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				s3c2410_dma_loadbuffer(chan, chan->next);
+			}
+
+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	}
+
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+/* s3c2410_dma_canload
+ *
+ * work out if we can queue another buffer into the DMA engine
+*/
+
+static int
+s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
+{
+	if (chan->load_state == S3C2410_DMALOAD_NONE ||
+	    chan->load_state == S3C2410_DMALOAD_1RUNNING)
+		return 1;
+
+	return 0;
+}
+
+/* s3c2410_dma_enqueue
+ *
+ * queue an given buffer for dma transfer.
+ *
+ * id         the device driver's id information for this buffer
+ * data       the physical address of the buffer data
+ * size       the size of the buffer in bytes
+ *
+ * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
+ * is checked, and if set, the channel is started. If this flag isn't set,
+ * then an error will be returned.
+ *
+ * It is possible to queue more than one DMA buffer onto a channel at
+ * once, and the code will deal with the re-loading of the next buffer
+ * when necessary.
+*/
+
+int s3c2410_dma_enqueue(unsigned int channel, void *id,
+			dma_addr_t data, int size)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	struct s3c2410_dma_buf *buf;
+	unsigned long flags;
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: id=%p, data=%08x, size=%d\n",
+		 __FUNCTION__, id, (unsigned int)data, size);
+
+	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
+	if (buf == NULL) {
+		pr_debug("%s: out of memory (%ld alloc)\n",
+			 __FUNCTION__, (long)sizeof(*buf));
+		return -ENOMEM;
+	}
+
+	//pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
+	//dbg_showchan(chan);
+
+	buf->next  = NULL;
+	buf->data  = buf->ptr = data;
+	buf->size  = size;
+	buf->id    = id;
+	buf->magic = BUF_MAGIC;
+
+	local_irq_save(flags);
+
+	if (chan->curr == NULL) {
+		/* we've got nothing loaded... */
+		pr_debug("%s: buffer %p queued onto empty channel\n",
+			 __FUNCTION__, buf);
+
+		chan->curr = buf;
+		chan->end  = buf;
+		chan->next = NULL;
+	} else {
+		pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
+			 chan->number, __FUNCTION__, buf);
+
+		if (chan->end == NULL)
+			pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
+				 chan->number, __FUNCTION__, chan);
+
+		chan->end->next = buf;
+		chan->end = buf;
+	}
+
+	/* if necessary, update the next buffer field */
+	if (chan->next == NULL)
+		chan->next = buf;
+
+	/* check to see if we can load a buffer */
+	if (chan->state == S3C2410_DMA_RUNNING) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				printk(KERN_ERR "dma%d: loadbuffer:"
+				       "timeout loading buffer\n",
+				       chan->number);
+				dbg_showchan(chan);
+				local_irq_restore(flags);
+				return -EINVAL;
+			}
+		}
+
+		while (s3c2410_dma_canload(chan) && chan->next != NULL) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	} else if (chan->state == S3C2410_DMA_IDLE) {
+		if (chan->flags & S3C2410_DMAF_AUTOSTART) {
+			s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
+		}
+	}
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_enqueue);
+
+static inline void
+s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
+{
+	int magicok = (buf->magic == BUF_MAGIC);
+
+	buf->magic = -1;
+
+	if (magicok) {
+		kmem_cache_free(dma_kmem, buf);
+	} else {
+		printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
+	}
+}
+
+/* s3c2410_dma_lastxfer
+ *
+ * called when the system is out of buffers, to ensure that the channel
+ * is prepared for shutdown.
+*/
+
+static inline void
+s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
+{
+#if 0
+	pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
+		 chan->number, chan->load_state);
+#endif
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_NONE:
+		break;
+
+	case S3C2410_DMALOAD_1LOADED:
+		if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				/* flag error? */
+			printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+			       chan->number, __FUNCTION__);
+			return;
+		}
+		break;
+
+	case S3C2410_DMALOAD_1LOADED_1RUNNING:
+		/* I belive in this case we do not have anything to do
+		 * until the next buffer comes along, and we turn off the
+		 * reload */
+		return;
+
+	default:
+		pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
+			 chan->number, chan->load_state);
+		return;
+
+	}
+
+	/* hopefully this'll shut the damned thing up after the transfer... */
+	dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
+}
+
+
+#define dmadbg2(x...)
+
+static irqreturn_t
+s3c2410_dma_irq(int irq, void *devpw)
+{
+	struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
+	struct s3c2410_dma_buf  *buf;
+
+	buf = chan->curr;
+
+	dbg_showchan(chan);
+
+	/* modify the channel state */
+
+	switch (chan->load_state) {
+	case S3C2410_DMALOAD_1RUNNING:
+		/* TODO - if we are running only one buffer, we probably
+		 * want to reload here, and then worry about the buffer
+		 * callback */
+
+		chan->load_state = S3C2410_DMALOAD_NONE;
+		break;
+
+	case S3C2410_DMALOAD_1LOADED:
+		/* iirc, we should go back to NONE loaded here, we
+		 * had a buffer, and it was never verified as being
+		 * loaded.
+		 */
+
+		chan->load_state = S3C2410_DMALOAD_NONE;
+		break;
+
+	case S3C2410_DMALOAD_1LOADED_1RUNNING:
+		/* we'll worry about checking to see if another buffer is
+		 * ready after we've called back the owner. This should
+		 * ensure we do not wait around too long for the DMA
+		 * engine to start the next transfer
+		 */
+
+		chan->load_state = S3C2410_DMALOAD_1LOADED;
+		break;
+
+	case S3C2410_DMALOAD_NONE:
+		printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
+		       chan->number);
+		break;
+
+	default:
+		printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
+		       chan->number, chan->load_state);
+		break;
+	}
+
+	if (buf != NULL) {
+		/* update the chain to make sure that if we load any more
+		 * buffers when we call the callback function, things should
+		 * work properly */
+
+		chan->curr = buf->next;
+		buf->next  = NULL;
+
+		if (buf->magic != BUF_MAGIC) {
+			printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
+			       chan->number, __FUNCTION__, buf);
+			return IRQ_HANDLED;
+		}
+
+		s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
+
+		/* free resouces */
+		s3c2410_dma_freebuf(buf);
+	} else {
+	}
+
+	/* only reload if the channel is still running... our buffer done
+	 * routine may have altered the state by requesting the dma channel
+	 * to stop or shutdown... */
+
+	/* todo: check that when the channel is shut-down from inside this
+	 * function, we cope with unsetting reload, etc */
+
+	if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
+		unsigned long flags;
+
+		switch (chan->load_state) {
+		case S3C2410_DMALOAD_1RUNNING:
+			/* don't need to do anything for this state */
+			break;
+
+		case S3C2410_DMALOAD_NONE:
+			/* can load buffer immediately */
+			break;
+
+		case S3C2410_DMALOAD_1LOADED:
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				/* flag error? */
+				printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+				       chan->number, __FUNCTION__);
+				return IRQ_HANDLED;
+			}
+
+			break;
+
+		case S3C2410_DMALOAD_1LOADED_1RUNNING:
+			goto no_load;
+
+		default:
+			printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
+			       chan->number, chan->load_state);
+			return IRQ_HANDLED;
+		}
+
+		local_irq_save(flags);
+		s3c2410_dma_loadbuffer(chan, chan->next);
+		local_irq_restore(flags);
+	} else {
+		s3c2410_dma_lastxfer(chan);
+
+		/* see if we can stop this channel.. */
+		if (chan->load_state == S3C2410_DMALOAD_NONE) {
+			pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
+				 chan->number, jiffies);
+			s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
+					 S3C2410_DMAOP_STOP);
+		}
+	}
+
+ no_load:
+	return IRQ_HANDLED;
+}
+
+static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
+
+/* s3c2410_request_dma
+ *
+ * get control of an dma channel
+*/
+
+int s3c2410_dma_request(unsigned int channel,
+			struct s3c2410_dma_client *client,
+			void *dev)
+{
+	struct s3c2410_dma_chan *chan;
+	unsigned long flags;
+	int err;
+
+	pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
+		 channel, client->name, dev);
+
+	local_irq_save(flags);
+
+	chan = s3c2410_dma_map_channel(channel);
+	if (chan == NULL) {
+		local_irq_restore(flags);
+		return -EBUSY;
+	}
+
+	dbg_showchan(chan);
+
+	chan->client = client;
+	chan->in_use = 1;
+
+	if (!chan->irq_claimed) {
+		pr_debug("dma%d: %s : requesting irq %d\n",
+			 channel, __FUNCTION__, chan->irq);
+
+		chan->irq_claimed = 1;
+		local_irq_restore(flags);
+
+		err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
+				  client->name, (void *)chan);
+
+		local_irq_save(flags);
+
+		if (err) {
+			chan->in_use = 0;
+			chan->irq_claimed = 0;
+			local_irq_restore(flags);
+
+			printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
+			       client->name, chan->irq, chan->number);
+			return err;
+		}
+
+		chan->irq_enabled = 1;
+	}
+
+	local_irq_restore(flags);
+
+	/* need to setup */
+
+	pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_request);
+
+/* s3c2410_dma_free
+ *
+ * release the given channel back to the system, will stop and flush
+ * any outstanding transfers, and ensure the channel is ready for the
+ * next claimant.
+ *
+ * Note, although a warning is currently printed if the freeing client
+ * info is not the same as the registrant's client info, the free is still
+ * allowed to go through.
+*/
+
+int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+	unsigned long flags;
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	if (chan->client != client) {
+		printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
+		       channel, chan->client, client);
+	}
+
+	/* sort out stopping and freeing the channel */
+
+	if (chan->state != S3C2410_DMA_IDLE) {
+		pr_debug("%s: need to stop dma channel %p\n",
+		       __FUNCTION__, chan);
+
+		/* possibly flush the channel */
+		s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
+	}
+
+	chan->client = NULL;
+	chan->in_use = 0;
+
+	if (chan->irq_claimed)
+		free_irq(chan->irq, (void *)chan);
+
+	chan->irq_claimed = 0;
+
+	if (!(channel & DMACH_LOW_LEVEL))
+		dma_chan_map[channel] = NULL;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_free);
+
+static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
+{
+	unsigned long flags;
+	unsigned long tmp;
+
+	pr_debug("%s:\n", __FUNCTION__);
+
+	dbg_showchan(chan);
+
+	local_irq_save(flags);
+
+	s3c2410_dma_call_op(chan,  S3C2410_DMAOP_STOP);
+
+	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+	tmp |= S3C2410_DMASKTRIG_STOP;
+	//tmp &= ~S3C2410_DMASKTRIG_ON;
+	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+	tmp |= S3C2410_DCON_NORELOAD;
+	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+#endif
+
+	/* should stop do this, or should we wait for flush? */
+	chan->state      = S3C2410_DMA_IDLE;
+	chan->load_state = S3C2410_DMALOAD_NONE;
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+{
+	unsigned long tmp;
+	unsigned int timeout = 0x10000;
+
+	while (timeout-- > 0) {
+		tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+
+		if (!(tmp & S3C2410_DMASKTRIG_ON))
+			return;
+	}
+
+	pr_debug("dma%d: failed to stop?\n", chan->number);
+}
+
+
+/* s3c2410_dma_flush
+ *
+ * stop the channel, and remove all current and pending transfers
+*/
+
+static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_buf *buf, *next;
+	unsigned long flags;
+
+	pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
+
+	dbg_showchan(chan);
+
+	local_irq_save(flags);
+
+	if (chan->state != S3C2410_DMA_IDLE) {
+		pr_debug("%s: stopping channel...\n", __FUNCTION__ );
+		s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
+	}
+
+	buf = chan->curr;
+	if (buf == NULL)
+		buf = chan->next;
+
+	chan->curr = chan->next = chan->end = NULL;
+
+	if (buf != NULL) {
+		for ( ; buf != NULL; buf = next) {
+			next = buf->next;
+
+			pr_debug("%s: free buffer %p, next %p\n",
+			       __FUNCTION__, buf, buf->next);
+
+			s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
+			s3c2410_dma_freebuf(buf);
+		}
+	}
+
+	dbg_showregs(chan);
+
+	s3c2410_dma_waitforstop(chan);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	{
+		unsigned long tmp;
+
+		tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+		tmp |= S3C2410_DCON_NORELOAD;
+		dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+	}
+#endif
+
+	dbg_showregs(chan);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+int
+s3c2410_dma_started(struct s3c2410_dma_chan *chan)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	dbg_showchan(chan);
+
+	/* if we've only loaded one buffer onto the channel, then chec
+	 * to see if we have another, and if so, try and load it so when
+	 * the first buffer is finished, the new one will be loaded onto
+	 * the channel */
+
+	if (chan->next != NULL) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				pr_debug("%s: buff not yet loaded, no more todo\n",
+					 __FUNCTION__);
+			} else {
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				s3c2410_dma_loadbuffer(chan, chan->next);
+			}
+
+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	}
+
+
+	local_irq_restore(flags);
+
+	return 0;
+
+}
+
+int
+s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	switch (op) {
+	case S3C2410_DMAOP_START:
+		return s3c2410_dma_start(chan);
+
+	case S3C2410_DMAOP_STOP:
+		return s3c2410_dma_dostop(chan);
+
+	case S3C2410_DMAOP_PAUSE:
+	case S3C2410_DMAOP_RESUME:
+		return -ENOENT;
+
+	case S3C2410_DMAOP_FLUSH:
+		return s3c2410_dma_flush(chan);
+
+	case S3C2410_DMAOP_STARTED:
+		return s3c2410_dma_started(chan);
+
+	case S3C2410_DMAOP_TIMEOUT:
+		return 0;
+
+	}
+
+	return -ENOENT;      /* unknown, don't bother */
+}
+
+EXPORT_SYMBOL(s3c2410_dma_ctrl);
+
+/* DMA configuration for each channel
+ *
+ * DISRCC -> source of the DMA (AHB,APB)
+ * DISRC  -> source address of the DMA
+ * DIDSTC -> destination of the DMA (AHB,APD)
+ * DIDST  -> destination address of the DMA
+*/
+
+/* s3c2410_dma_config
+ *
+ * xfersize:     size of unit in bytes (1,2,4)
+ * dcon:         base value of the DCONx register
+*/
+
+int s3c2410_dma_config(dmach_t channel,
+		       int xferunit,
+		       int dcon)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
+		 __FUNCTION__, channel, xferunit, dcon);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
+
+	dcon |= chan->dcon & dma_sel.dcon_mask;
+
+	pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
+
+	switch (xferunit) {
+	case 1:
+		dcon |= S3C2410_DCON_BYTE;
+		break;
+
+	case 2:
+		dcon |= S3C2410_DCON_HALFWORD;
+		break;
+
+	case 4:
+		dcon |= S3C2410_DCON_WORD;
+		break;
+
+	default:
+		pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
+		return -EINVAL;
+	}
+
+	dcon |= S3C2410_DCON_HWTRIG;
+	dcon |= S3C2410_DCON_INTREQ;
+
+	pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
+
+	chan->dcon = dcon;
+	chan->xfer_unit = xferunit;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_config);
+
+int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
+
+	chan->flags = flags;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_setflags);
+
+
+/* do we need to protect the settings of the fields from
+ * irq?
+*/
+
+int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
+
+	chan->op_fn = rtn;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_opfn);
+
+int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
+
+	chan->callback_fn = rtn;
+
+	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
+
+/* s3c2410_dma_devconfig
+ *
+ * configure the dma source/destination hardware type and address
+ *
+ * source:    S3C2410_DMASRC_HW: source is hardware
+ *            S3C2410_DMASRC_MEM: source is memory
+ *
+ * hwcfg:     the value for xxxSTCn register,
+ *            bit 0: 0=increment pointer, 1=leave pointer
+ *            bit 1: 0=soucre is AHB, 1=soucre is APB
+ *
+ * devaddr:   physical address of the source
+*/
+
+int s3c2410_dma_devconfig(int channel,
+			  enum s3c2410_dmasrc source,
+			  int hwcfg,
+			  unsigned long devaddr)
+{
+	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
+		 __FUNCTION__, (int)source, hwcfg, devaddr);
+
+	chan->source = source;
+	chan->dev_addr = devaddr;
+
+	switch (source) {
+	case S3C2410_DMASRC_HW:
+		/* source is hardware */
+		pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
+			 __FUNCTION__, devaddr, hwcfg);
+		dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
+		dma_wrreg(chan, S3C2410_DMA_DISRC,  devaddr);
+		dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
+
+		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
+		return 0;
+
+	case S3C2410_DMASRC_MEM:
+		/* source is memory */
+		pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
+			  __FUNCTION__, devaddr, hwcfg);
+		dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
+		dma_wrreg(chan, S3C2410_DMA_DIDST,  devaddr);
+		dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
+
+		chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
+		return 0;
+	}
+
+	printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
+	return -EINVAL;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_devconfig);
+
+/* s3c2410_dma_getposition
+ *
+ * returns the current transfer points for the dma source and destination
+*/
+
+int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
+{
+ 	struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
+
+	if (chan == NULL)
+		return -EINVAL;
+
+	if (src != NULL)
+ 		*src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
+
+ 	if (dst != NULL)
+ 		*dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
+
+ 	return 0;
+}
+
+EXPORT_SYMBOL(s3c2410_dma_getposition);
+
+
+/* system device class */
+
+#ifdef CONFIG_PM
+
+static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
+
+	printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
+
+	if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
+		/* the dma channel is still working, which is probably
+		 * a bad thing to do over suspend/resume. We stop the
+		 * channel and assume that the client is either going to
+		 * retry after resume, or that it is broken.
+		 */
+
+		printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
+		       cp->number);
+
+		s3c2410_dma_dostop(cp);
+	}
+
+	return 0;
+}
+
+static int s3c2410_dma_resume(struct sys_device *dev)
+{
+	return 0;
+}
+
+#else
+#define s3c2410_dma_suspend NULL
+#define s3c2410_dma_resume  NULL
+#endif /* CONFIG_PM */
+
+struct sysdev_class dma_sysclass = {
+	set_kset_name("s3c24xx-dma"),
+	.suspend	= s3c2410_dma_suspend,
+	.resume		= s3c2410_dma_resume,
+};
+
+/* kmem cache implementation */
+
+static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
+{
+	memset(p, 0, sizeof(struct s3c2410_dma_buf));
+}
+
+/* initialisation code */
+
+static int __init s3c2410_init_dma(void)
+{
+	struct s3c2410_dma_chan *cp;
+	int channel;
+	int ret;
+
+	printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
+
+	dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
+	if (dma_base == NULL) {
+		printk(KERN_ERR "dma failed to remap register block\n");
+		return -ENOMEM;
+	}
+
+	printk("Registering sysclass\n");
+
+	ret = sysdev_class_register(&dma_sysclass);
+	if (ret != 0) {
+		printk(KERN_ERR "dma sysclass registration failed\n");
+		goto err;
+	}
+
+	dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
+				     SLAB_HWCACHE_ALIGN,
+				     s3c2410_dma_cache_ctor, NULL);
+
+	if (dma_kmem == NULL) {
+		printk(KERN_ERR "dma failed to make kmem cache\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
+		cp = &s3c2410_chans[channel];
+
+		memset(cp, 0, sizeof(struct s3c2410_dma_chan));
+
+		/* dma channel irqs are in order.. */
+		cp->number = channel;
+		cp->irq    = channel + IRQ_DMA0;
+		cp->regs   = dma_base + (channel*0x40);
+
+		/* point current stats somewhere */
+		cp->stats  = &cp->stats_store;
+		cp->stats_store.timeout_shortest = LONG_MAX;
+
+		/* basic channel configuration */
+
+		cp->load_timeout = 1<<18;
+
+		/* register system device */
+
+		cp->dev.cls = &dma_sysclass;
+		cp->dev.id  = channel;
+		ret = sysdev_register(&cp->dev);
+
+		printk("DMA channel %d at %p, irq %d\n",
+		       cp->number, cp->regs, cp->irq);
+	}
+
+	return 0;
+
+ err:
+	kmem_cache_destroy(dma_kmem);
+	iounmap(dma_base);
+	dma_base = NULL;
+	return ret;
+}
+
+core_initcall(s3c2410_init_dma);
+
+static inline int is_channel_valid(unsigned int channel)
+{
+	return (channel & DMA_CH_VALID);
+}
+
+/* s3c2410_dma_map_channel()
+ *
+ * turn the virtual channel number into a real, and un-used hardware
+ * channel.
+ *
+ * currently this code uses first-free channel from the specified harware
+ * map, not taking into account anything that the board setup code may
+ * have to say about the likely peripheral set to be in use.
+*/
+
+struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
+{
+	struct s3c24xx_dma_map *ch_map;
+	struct s3c2410_dma_chan *dmach;
+	int ch;
+
+	if (dma_sel.map == NULL || channel > dma_sel.map_size)
+		return NULL;
+
+	ch_map = dma_sel.map + channel;
+
+	for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
+		if (!is_channel_valid(ch_map->channels[ch]))
+			continue;
+
+		if (s3c2410_chans[ch].in_use == 0) {
+			printk("mapped channel %d to %d\n", channel, ch);
+			break;
+		}
+	}
+
+	if (ch >= S3C2410_DMA_CHANNELS)
+		return NULL;
+
+	/* update our channel mapping */
+
+	dmach = &s3c2410_chans[ch];
+	dma_chan_map[channel] = dmach;
+
+	/* select the channel */
+
+	(dma_sel.select)(dmach, ch_map);
+
+	return dmach;
+}
+
+static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
+{
+	/* show the channel configuration */
+
+	printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
+	       (is_channel_valid(map->channels[0]) ? '0' : '-'),
+	       (is_channel_valid(map->channels[1]) ? '1' : '-'),
+	       (is_channel_valid(map->channels[2]) ? '2' : '-'),
+	       (is_channel_valid(map->channels[3]) ? '3' : '-'));
+}
+
+static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
+{
+	if (1)
+		s3c24xx_dma_show_ch(map, ch);
+
+	return 0;
+}
+
+int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
+{
+	struct s3c24xx_dma_map *nmap;
+	size_t map_sz = sizeof(*nmap) * sel->map_size;
+	int ptr;
+
+	nmap = kmalloc(map_sz, GFP_KERNEL);
+	if (nmap == NULL)
+		return -ENOMEM;
+
+	memcpy(nmap, sel->map, map_sz);
+	memcpy(&dma_sel, sel, sizeof(*sel));
+
+	dma_sel.map = nmap;
+
+	for (ptr = 0; ptr < sel->map_size; ptr++)
+		s3c24xx_dma_check_entry(nmap+ptr, ptr);
+
+	return 0;
+}
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
new file mode 100644
index 0000000..ec3a09c
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/gpio.c
@@ -0,0 +1,188 @@
+/* linux/arch/arm/plat-s3c24xx/gpio.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX GPIO support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-gpio.h>
+
+void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long mask;
+	unsigned long con;
+	unsigned long flags;
+
+	if (pin < S3C2410_GPIO_BANKB) {
+		mask = 1 << S3C2410_GPIO_OFFSET(pin);
+	} else {
+		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+	}
+
+	switch (function) {
+	case S3C2410_GPIO_LEAVE:
+		mask = 0;
+		function = 0;
+		break;
+
+	case S3C2410_GPIO_INPUT:
+	case S3C2410_GPIO_OUTPUT:
+	case S3C2410_GPIO_SFN2:
+	case S3C2410_GPIO_SFN3:
+		if (pin < S3C2410_GPIO_BANKB) {
+			function -= 1;
+			function &= 1;
+			function <<= S3C2410_GPIO_OFFSET(pin);
+		} else {
+			function &= 3;
+			function <<= S3C2410_GPIO_OFFSET(pin)*2;
+		}
+	}
+
+	/* modify the specified register wwith IRQs off */
+
+	local_irq_save(flags);
+
+	con  = __raw_readl(base + 0x00);
+	con &= ~mask;
+	con |= function;
+
+	__raw_writel(con, base + 0x00);
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
+
+unsigned int s3c2410_gpio_getcfg(unsigned int pin)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long val = __raw_readl(base);
+
+	if (pin < S3C2410_GPIO_BANKB) {
+		val >>= S3C2410_GPIO_OFFSET(pin);
+		val &= 1;
+		val += 1;
+	} else {
+		val >>= S3C2410_GPIO_OFFSET(pin)*2;
+		val &= 3;
+	}
+
+	return val | S3C2410_GPIO_INPUT;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getcfg);
+
+void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	unsigned long flags;
+	unsigned long up;
+
+	if (pin < S3C2410_GPIO_BANKB)
+		return;
+
+	local_irq_save(flags);
+
+	up = __raw_readl(base + 0x08);
+	up &= ~(1L << offs);
+	up |= to << offs;
+	__raw_writel(up, base + 0x08);
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_pullup);
+
+void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	unsigned long flags;
+	unsigned long dat;
+
+	local_irq_save(flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offs);
+	dat |= to << offs;
+	__raw_writel(dat, base + 0x04);
+
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_setpin);
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+
+	return __raw_readl(base + 0x04) & (1<< offs);
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getpin);
+
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+	unsigned long flags;
+	unsigned long misccr;
+
+	local_irq_save(flags);
+	misccr = __raw_readl(S3C24XX_MISCCR);
+	misccr &= ~clear;
+	misccr ^= change;
+	__raw_writel(misccr, S3C24XX_MISCCR);
+	local_irq_restore(flags);
+
+	return misccr;
+}
+
+EXPORT_SYMBOL(s3c2410_modify_misccr);
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
+		return -1;	/* not valid interrupts */
+
+	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+		return -1;	/* not valid pin */
+
+	if (pin < S3C2410_GPF4)
+		return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+	if (pin < S3C2410_GPG0)
+		return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+	return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+EXPORT_SYMBOL(s3c2410_gpio_getirq);
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
new file mode 100644
index 0000000..ce18639
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -0,0 +1,801 @@
+/* linux/arch/arm/plat-s3c24xx/irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Changelog:
+ *
+ *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
+ *                Fixed compile warnings
+ *
+ *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
+ *                Fixed s3c_extirq_type
+ *
+ *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+ *                Addition of ADC/TC demux
+ *
+ *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
+ *		  Fix for set_irq_type() on low EINT numbers
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *		  Tidy up KF's patch and sort out new release
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *		  Add support for power management controls
+ *
+ *   04-Nov-2004  Ben Dooks
+ *		  Fix standard IRQ wake for EINT0..4 and RTC
+ *
+ *   22-Feb-2005  Ben Dooks
+ *		  Fixed edge-triggering on ADC IRQ
+ *
+ *   28-Jun-2005  Ben Dooks
+ *		  Mark IRQ_LCD valid
+ *
+ *   25-Jul-2005  Ben Dooks
+ *		  Split the S3C2440 IRQ code to seperate file
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
+
+/* wakeup irq control */
+
+#ifdef CONFIG_PM
+
+/* state for IRQs over sleep */
+
+/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
+ *
+ * set bit to 1 in allow bitfield to enable the wakeup settings on it
+*/
+
+unsigned long s3c_irqwake_intallow	= 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
+unsigned long s3c_irqwake_intmask	= 0xffffffffL;
+unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
+unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
+
+int
+s3c_irq_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
+
+	if (!(s3c_irqwake_intallow & irqbit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_intmask |= irqbit;
+	else
+		s3c_irqwake_intmask &= ~irqbit;
+
+	return 0;
+}
+
+static int
+s3c_irqext_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long bit = 1L << (irqno - EXTINT_OFF);
+
+	if (!(s3c_irqwake_eintallow & bit))
+		return -ENOENT;
+
+	printk(KERN_INFO "wake %s for irq %d\n",
+	       state ? "enabled" : "disabled", irqno);
+
+	if (!state)
+		s3c_irqwake_eintmask |= bit;
+	else
+		s3c_irqwake_eintmask &= ~bit;
+
+	return 0;
+}
+
+#else
+#define s3c_irqext_wake NULL
+#define s3c_irq_wake NULL
+#endif
+
+
+static void
+s3c_irq_mask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	irqno -= IRQ_EINT0;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	mask |= 1UL << irqno;
+	__raw_writel(mask, S3C2410_INTMSK);
+}
+
+static inline void
+s3c_irq_ack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+static inline void
+s3c_irq_maskack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask|bitval, S3C2410_INTMSK);
+
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+
+static void
+s3c_irq_unmask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
+		irqdbf2("s3c_irq_unmask %d\n", irqno);
+
+	irqno -= IRQ_EINT0;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	mask &= ~(1UL << irqno);
+	__raw_writel(mask, S3C2410_INTMSK);
+}
+
+struct irq_chip s3c_irq_level_chip = {
+	.name		= "s3c-level",
+	.ack		= s3c_irq_maskack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake
+};
+
+static struct irq_chip s3c_irq_chip = {
+	.name		= "s3c",
+	.ack		= s3c_irq_ack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake
+};
+
+static void
+s3c_irqext_mask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	irqno -= EXTINT_OFF;
+
+	mask = __raw_readl(S3C24XX_EINTMASK);
+	mask |= ( 1UL << irqno);
+	__raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+static void
+s3c_irqext_ack(unsigned int irqno)
+{
+	unsigned long req;
+	unsigned long bit;
+	unsigned long mask;
+
+	bit = 1UL << (irqno - EXTINT_OFF);
+
+	mask = __raw_readl(S3C24XX_EINTMASK);
+
+	__raw_writel(bit, S3C24XX_EINTPEND);
+
+	req = __raw_readl(S3C24XX_EINTPEND);
+	req &= ~mask;
+
+	/* not sure if we should be acking the parent irq... */
+
+	if (irqno <= IRQ_EINT7 ) {
+		if ((req & 0xf0) == 0)
+			s3c_irq_ack(IRQ_EINT4t7);
+	} else {
+		if ((req >> 8) == 0)
+			s3c_irq_ack(IRQ_EINT8t23);
+	}
+}
+
+static void
+s3c_irqext_unmask(unsigned int irqno)
+{
+	unsigned long mask;
+
+	irqno -= EXTINT_OFF;
+
+	mask = __raw_readl(S3C24XX_EINTMASK);
+	mask &= ~( 1UL << irqno);
+	__raw_writel(mask, S3C24XX_EINTMASK);
+}
+
+int
+s3c_irqext_type(unsigned int irq, unsigned int type)
+{
+	void __iomem *extint_reg;
+	void __iomem *gpcon_reg;
+	unsigned long gpcon_offset, extint_offset;
+	unsigned long newvalue = 0, value;
+
+	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C24XX_EXTINT0;
+		gpcon_offset = (irq - IRQ_EINT0) * 2;
+		extint_offset = (irq - IRQ_EINT0) * 4;
+	}
+	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C24XX_EXTINT0;
+		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+		extint_offset = (irq - (EXTINT_OFF)) * 4;
+	}
+	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C24XX_EXTINT1;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT8) * 4;
+	}
+	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C24XX_EXTINT2;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT16) * 4;
+	} else
+		return -1;
+
+	/* Set the GPIO to external interrupt mode */
+	value = __raw_readl(gpcon_reg);
+	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+	__raw_writel(value, gpcon_reg);
+
+	/* Set the external interrupt to pointed trigger type */
+	switch (type)
+	{
+		case IRQT_NOEDGE:
+			printk(KERN_WARNING "No edge setting!\n");
+			break;
+
+		case IRQT_RISING:
+			newvalue = S3C2410_EXTINT_RISEEDGE;
+			break;
+
+		case IRQT_FALLING:
+			newvalue = S3C2410_EXTINT_FALLEDGE;
+			break;
+
+		case IRQT_BOTHEDGE:
+			newvalue = S3C2410_EXTINT_BOTHEDGE;
+			break;
+
+		case IRQT_LOW:
+			newvalue = S3C2410_EXTINT_LOWLEV;
+			break;
+
+		case IRQT_HIGH:
+			newvalue = S3C2410_EXTINT_HILEV;
+			break;
+
+		default:
+			printk(KERN_ERR "No such irq type %d", type);
+			return -1;
+	}
+
+	value = __raw_readl(extint_reg);
+	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+	__raw_writel(value, extint_reg);
+
+	return 0;
+}
+
+static struct irq_chip s3c_irqext_chip = {
+	.name		= "s3c-ext",
+	.mask		= s3c_irqext_mask,
+	.unmask		= s3c_irqext_unmask,
+	.ack		= s3c_irqext_ack,
+	.set_type	= s3c_irqext_type,
+	.set_wake	= s3c_irqext_wake
+};
+
+static struct irq_chip s3c_irq_eint0t4 = {
+	.name		= "s3c-ext0",
+	.ack		= s3c_irq_ack,
+	.mask		= s3c_irq_mask,
+	.unmask		= s3c_irq_unmask,
+	.set_wake	= s3c_irq_wake,
+	.set_type	= s3c_irqext_type,
+};
+
+/* mask values for the parent registers for each of the interrupt types */
+
+#define INTMSK_UART0	 (1UL << (IRQ_UART0 - IRQ_EINT0))
+#define INTMSK_UART1	 (1UL << (IRQ_UART1 - IRQ_EINT0))
+#define INTMSK_UART2	 (1UL << (IRQ_UART2 - IRQ_EINT0))
+#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
+
+
+/* UART0 */
+
+static void
+s3c_irq_uart0_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
+}
+
+static void
+s3c_irq_uart0_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_UART0);
+}
+
+static void
+s3c_irq_uart0_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
+}
+
+static struct irq_chip s3c_irq_uart0 = {
+	.name		= "s3c-uart0",
+	.mask		= s3c_irq_uart0_mask,
+	.unmask		= s3c_irq_uart0_unmask,
+	.ack		= s3c_irq_uart0_ack,
+};
+
+/* UART1 */
+
+static void
+s3c_irq_uart1_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static void
+s3c_irq_uart1_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_UART1);
+}
+
+static void
+s3c_irq_uart1_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
+}
+
+static struct irq_chip s3c_irq_uart1 = {
+	.name		= "s3c-uart1",
+	.mask		= s3c_irq_uart1_mask,
+	.unmask		= s3c_irq_uart1_unmask,
+	.ack		= s3c_irq_uart1_ack,
+};
+
+/* UART2 */
+
+static void
+s3c_irq_uart2_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static void
+s3c_irq_uart2_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_UART2);
+}
+
+static void
+s3c_irq_uart2_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
+}
+
+static struct irq_chip s3c_irq_uart2 = {
+	.name		= "s3c-uart2",
+	.mask		= s3c_irq_uart2_mask,
+	.unmask		= s3c_irq_uart2_unmask,
+	.ack		= s3c_irq_uart2_ack,
+};
+
+/* ADC and Touchscreen */
+
+static void
+s3c_irq_adc_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static void
+s3c_irq_adc_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
+}
+
+static void
+s3c_irq_adc_ack(unsigned int irqno)
+{
+	s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
+}
+
+static struct irq_chip s3c_irq_adc = {
+	.name		= "s3c-adc",
+	.mask		= s3c_irq_adc_mask,
+	.unmask		= s3c_irq_adc_unmask,
+	.ack		= s3c_irq_adc_ack,
+};
+
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+			      struct irq_desc *desc)
+{
+	unsigned int subsrc, submsk;
+	unsigned int offset = 9;
+	struct irq_desc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= offset;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_TC;
+			desc_handle_irq(IRQ_TC, mydesc);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_ADC;
+			desc_handle_irq(IRQ_ADC, mydesc);
+		}
+	}
+}
+
+static void s3c_irq_demux_uart(unsigned int start)
+{
+	unsigned int subsrc, submsk;
+	unsigned int offset = start - IRQ_S3CUART_RX0;
+	struct irq_desc *desc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
+		start, offset, subsrc, submsk);
+
+	subsrc &= ~submsk;
+	subsrc >>= offset;
+	subsrc &= 7;
+
+	if (subsrc != 0) {
+		desc = irq_desc + start;
+
+		if (subsrc & 1)
+			desc_handle_irq(start, desc);
+
+		desc++;
+
+		if (subsrc & 2)
+			desc_handle_irq(start+1, desc);
+
+		desc++;
+
+		if (subsrc & 4)
+			desc_handle_irq(start+2, desc);
+	}
+}
+
+/* uart demux entry points */
+
+static void
+s3c_irq_demux_uart0(unsigned int irq,
+		    struct irq_desc *desc)
+{
+	irq = irq;
+	s3c_irq_demux_uart(IRQ_S3CUART_RX0);
+}
+
+static void
+s3c_irq_demux_uart1(unsigned int irq,
+		    struct irq_desc *desc)
+{
+	irq = irq;
+	s3c_irq_demux_uart(IRQ_S3CUART_RX1);
+}
+
+static void
+s3c_irq_demux_uart2(unsigned int irq,
+		    struct irq_desc *desc)
+{
+	irq = irq;
+	s3c_irq_demux_uart(IRQ_S3CUART_RX2);
+}
+
+static void
+s3c_irq_demux_extint8(unsigned int irq,
+		      struct irq_desc *desc)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+	eintpnd &= ~0xff;	/* ignore lower irqs */
+
+	/* we may as well handle all the pending IRQs here */
+
+	while (eintpnd) {
+		irq = __ffs(eintpnd);
+		eintpnd &= ~(1<<irq);
+
+		irq += (IRQ_EINT4 - 4);
+		desc_handle_irq(irq, irq_desc + irq);
+	}
+
+}
+
+static void
+s3c_irq_demux_extint4t7(unsigned int irq,
+			struct irq_desc *desc)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+	eintpnd &= 0xff;	/* only lower irqs */
+
+	/* we may as well handle all the pending IRQs here */
+
+	while (eintpnd) {
+		irq = __ffs(eintpnd);
+		eintpnd &= ~(1<<irq);
+
+		irq += (IRQ_EINT4 - 4);
+
+		desc_handle_irq(irq, irq_desc + irq);
+	}
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save irq_save[] = {
+	SAVE_ITEM(S3C2410_INTMSK),
+	SAVE_ITEM(S3C2410_INTSUBMSK),
+};
+
+/* the extint values move between the s3c2410/s3c2440 and the s3c2412
+ * so we use an array to hold them, and to calculate the address of
+ * the register at run-time
+*/
+
+static unsigned long save_extint[3];
+static unsigned long save_eintflt[4];
+static unsigned long save_eintmask;
+
+int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
+
+	s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
+	save_eintmask = __raw_readl(S3C24XX_EINTMASK);
+
+	return 0;
+}
+
+int s3c24xx_irq_resume(struct sys_device *dev)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(save_extint); i++)
+		__raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
+
+	for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
+		__raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
+
+	s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
+	__raw_writel(save_eintmask, S3C24XX_EINTMASK);
+
+	return 0;
+}
+
+#else
+#define s3c24xx_irq_suspend NULL
+#define s3c24xx_irq_resume  NULL
+#endif
+
+/* s3c24xx_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
+
+void __init s3c24xx_init_irq(void)
+{
+	unsigned long pend;
+	unsigned long last;
+	int irqno;
+	int i;
+
+	irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
+
+	/* first, clear all interrupts pending... */
+
+	last = 0;
+	for (i = 0; i < 4; i++) {
+		pend = __raw_readl(S3C24XX_EINTPEND);
+
+		if (pend == 0 || pend == last)
+			break;
+
+		__raw_writel(pend, S3C24XX_EINTPEND);
+		printk("irq: clearing pending ext status %08x\n", (int)pend);
+		last = pend;
+	}
+
+	last = 0;
+	for (i = 0; i < 4; i++) {
+		pend = __raw_readl(S3C2410_INTPND);
+
+		if (pend == 0 || pend == last)
+			break;
+
+		__raw_writel(pend, S3C2410_SRCPND);
+		__raw_writel(pend, S3C2410_INTPND);
+		printk("irq: clearing pending status %08x\n", (int)pend);
+		last = pend;
+	}
+
+	last = 0;
+	for (i = 0; i < 4; i++) {
+		pend = __raw_readl(S3C2410_SUBSRCPND);
+
+		if (pend == 0 || pend == last)
+			break;
+
+		printk("irq: clearing subpending status %08x\n", (int)pend);
+		__raw_writel(pend, S3C2410_SUBSRCPND);
+		last = pend;
+	}
+
+	/* register the main interrupts */
+
+	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
+
+	for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
+		/* set all the s3c2410 internal irqs */
+
+		switch (irqno) {
+			/* deal with the special IRQs (cascaded) */
+
+		case IRQ_EINT4t7:
+		case IRQ_EINT8t23:
+		case IRQ_UART0:
+		case IRQ_UART1:
+		case IRQ_UART2:
+		case IRQ_ADCPARENT:
+			set_irq_chip(irqno, &s3c_irq_level_chip);
+			set_irq_handler(irqno, handle_level_irq);
+			break;
+
+		case IRQ_RESERVED6:
+		case IRQ_RESERVED24:
+			/* no IRQ here */
+			break;
+
+		default:
+			//irqdbf("registering irq %d (s3c irq)\n", irqno);
+			set_irq_chip(irqno, &s3c_irq_chip);
+			set_irq_handler(irqno, handle_edge_irq);
+			set_irq_flags(irqno, IRQF_VALID);
+		}
+	}
+
+	/* setup the cascade irq handlers */
+
+	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
+
+	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
+	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
+	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
+	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
+
+	/* external interrupts */
+
+	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+		irqdbf("registering irq %d (ext int)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_eint0t4);
+		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
+		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irqext_chip);
+		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	/* register the uart interrupts */
+
+	irqdbf("s3c2410: registering external interrupts\n");
+
+	for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
+		irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_uart0);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
+		irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_uart1);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
+		irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_uart2);
+		set_irq_handler(irqno, handle_level_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
+		irqdbf("registering irq %d (s3c adc irq)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_adc);
+		set_irq_handler(irqno, handle_edge_irq);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	irqdbf("s3c2410: registered interrupt handlers\n");
+}
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c
similarity index 94%
rename from arch/arm/mach-s3c2410/pm-simtec.c
rename to arch/arm/plat-s3c24xx/pm-simtec.c
index 619133e..bd965f2 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/plat-s3c24xx/pm-simtec.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/pm-simtec.c
+/* linux/arch/arm/plat-s3c24xx/pm-simtec.c
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -32,7 +32,7 @@
 
 #include <asm/mach-types.h>
 
-#include "pm.h"
+#include <asm/plat-s3c24xx/pm.h>
 
 #define COPYRIGHT ", (c) 2005 Simtec Electronics"
 
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
new file mode 100644
index 0000000..ecf68d6
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -0,0 +1,659 @@
+/* linux/arch/arm/plat-s3c24xx/pm.c
+ *
+ * Copyright (c) 2004,2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C24XX Power Manager (Suspend-To-RAM) support
+ *
+ * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Parts based on arch/arm/mach-pxa/pm.c
+ *
+ * Thanks to Dimitry Andric for debugging
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <linux/crc32.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/serial_core.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-irq.h>
+
+#include <asm/mach/time.h>
+
+#include <asm/plat-s3c24xx/pm.h>
+
+/* for external use */
+
+unsigned long s3c_pm_flags;
+
+#define PFX "s3c24xx-pm: "
+
+static struct sleep_save core_save[] = {
+	SAVE_ITEM(S3C2410_LOCKTIME),
+	SAVE_ITEM(S3C2410_CLKCON),
+
+	/* we restore the timings here, with the proviso that the board
+	 * brings the system up in an slower, or equal frequency setting
+	 * to the original system.
+	 *
+	 * if we cannot guarantee this, then things are going to go very
+	 * wrong here, as we modify the refresh and both pll settings.
+	 */
+
+	SAVE_ITEM(S3C2410_BWSCON),
+	SAVE_ITEM(S3C2410_BANKCON0),
+	SAVE_ITEM(S3C2410_BANKCON1),
+	SAVE_ITEM(S3C2410_BANKCON2),
+	SAVE_ITEM(S3C2410_BANKCON3),
+	SAVE_ITEM(S3C2410_BANKCON4),
+	SAVE_ITEM(S3C2410_BANKCON5),
+
+	SAVE_ITEM(S3C2410_CLKDIVN),
+	SAVE_ITEM(S3C2410_MPLLCON),
+	SAVE_ITEM(S3C2410_UPLLCON),
+	SAVE_ITEM(S3C2410_CLKSLOW),
+	SAVE_ITEM(S3C2410_REFRESH),
+};
+
+static struct sleep_save gpio_save[] = {
+	SAVE_ITEM(S3C2410_GPACON),
+	SAVE_ITEM(S3C2410_GPADAT),
+
+	SAVE_ITEM(S3C2410_GPBCON),
+	SAVE_ITEM(S3C2410_GPBDAT),
+	SAVE_ITEM(S3C2410_GPBUP),
+
+	SAVE_ITEM(S3C2410_GPCCON),
+	SAVE_ITEM(S3C2410_GPCDAT),
+	SAVE_ITEM(S3C2410_GPCUP),
+
+	SAVE_ITEM(S3C2410_GPDCON),
+	SAVE_ITEM(S3C2410_GPDDAT),
+	SAVE_ITEM(S3C2410_GPDUP),
+
+	SAVE_ITEM(S3C2410_GPECON),
+	SAVE_ITEM(S3C2410_GPEDAT),
+	SAVE_ITEM(S3C2410_GPEUP),
+
+	SAVE_ITEM(S3C2410_GPFCON),
+	SAVE_ITEM(S3C2410_GPFDAT),
+	SAVE_ITEM(S3C2410_GPFUP),
+
+	SAVE_ITEM(S3C2410_GPGCON),
+	SAVE_ITEM(S3C2410_GPGDAT),
+	SAVE_ITEM(S3C2410_GPGUP),
+
+	SAVE_ITEM(S3C2410_GPHCON),
+	SAVE_ITEM(S3C2410_GPHDAT),
+	SAVE_ITEM(S3C2410_GPHUP),
+
+	SAVE_ITEM(S3C2410_DCLKCON),
+};
+
+#ifdef CONFIG_S3C2410_PM_DEBUG
+
+#define SAVE_UART(va) \
+	SAVE_ITEM((va) + S3C2410_ULCON), \
+	SAVE_ITEM((va) + S3C2410_UCON), \
+	SAVE_ITEM((va) + S3C2410_UFCON), \
+	SAVE_ITEM((va) + S3C2410_UMCON), \
+	SAVE_ITEM((va) + S3C2410_UBRDIV)
+
+static struct sleep_save uart_save[] = {
+	SAVE_UART(S3C24XX_VA_UART0),
+	SAVE_UART(S3C24XX_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+	SAVE_UART(S3C24XX_VA_UART2),
+#endif
+};
+
+/* debug
+ *
+ * we send the debug to printascii() to allow it to be seen if the
+ * system never wakes up from the sleep
+*/
+
+extern void printascii(const char *);
+
+void pm_dbg(const char *fmt, ...)
+{
+	va_list va;
+	char buff[256];
+
+	va_start(va, fmt);
+	vsprintf(buff, fmt, va);
+	va_end(va);
+
+	printascii(buff);
+}
+
+static void s3c2410_pm_debug_init(void)
+{
+	unsigned long tmp = __raw_readl(S3C2410_CLKCON);
+
+	/* re-start uart clocks */
+	tmp |= S3C2410_CLKCON_UART0;
+	tmp |= S3C2410_CLKCON_UART1;
+	tmp |= S3C2410_CLKCON_UART2;
+
+	__raw_writel(tmp, S3C2410_CLKCON);
+	udelay(10);
+}
+
+#define DBG(fmt...) pm_dbg(fmt)
+#else
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
+
+#define s3c2410_pm_debug_init() do { } while(0)
+
+static struct sleep_save uart_save[] = {};
+#endif
+
+#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
+
+/* suspend checking code...
+ *
+ * this next area does a set of crc checks over all the installed
+ * memory, so the system can verify if the resume was ok.
+ *
+ * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
+ * increasing it will mean that the area corrupted will be less easy to spot,
+ * and reducing the size will cause the CRC save area to grow
+*/
+
+#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
+
+static u32 crc_size;	/* size needed for the crc block */
+static u32 *crcs;	/* allocated over suspend/resume */
+
+typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
+
+/* s3c2410_pm_run_res
+ *
+ * go thorugh the given resource list, and look for system ram
+*/
+
+static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
+{
+	while (ptr != NULL) {
+		if (ptr->child != NULL)
+			s3c2410_pm_run_res(ptr->child, fn, arg);
+
+		if ((ptr->flags & IORESOURCE_MEM) &&
+		    strcmp(ptr->name, "System RAM") == 0) {
+			DBG("Found system RAM at %08lx..%08lx\n",
+			    ptr->start, ptr->end);
+			arg = (fn)(ptr, arg);
+		}
+
+		ptr = ptr->sibling;
+	}
+}
+
+static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
+{
+	s3c2410_pm_run_res(&iomem_resource, fn, arg);
+}
+
+static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
+{
+	u32 size = (u32)(res->end - res->start)+1;
+
+	size += CHECK_CHUNKSIZE-1;
+	size /= CHECK_CHUNKSIZE;
+
+	DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
+
+	*val += size * sizeof(u32);
+	return val;
+}
+
+/* s3c2410_pm_prepare_check
+ *
+ * prepare the necessary information for creating the CRCs. This
+ * must be done before the final save, as it will require memory
+ * allocating, and thus touching bits of the kernel we do not
+ * know about.
+*/
+
+static void s3c2410_pm_check_prepare(void)
+{
+	crc_size = 0;
+
+	s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+
+	DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+
+	crcs = kmalloc(crc_size+4, GFP_KERNEL);
+	if (crcs == NULL)
+		printk(KERN_ERR "Cannot allocated CRC save area\n");
+}
+
+static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
+{
+	unsigned long addr, left;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		*val = crc32_le(~0, phys_to_virt(addr), left);
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c2410_pm_check_store
+ *
+ * compute the CRC values for the memory blocks before the final
+ * sleep.
+*/
+
+static void s3c2410_pm_check_store(void)
+{
+	if (crcs != NULL)
+		s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
+}
+
+/* in_region
+ *
+ * return TRUE if the area defined by ptr..ptr+size contatins the
+ * what..what+whatsz
+*/
+
+static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
+{
+	if ((what+whatsz) < ptr)
+		return 0;
+
+	if (what > (ptr+size))
+		return 0;
+
+	return 1;
+}
+
+static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
+{
+	void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
+	unsigned long addr;
+	unsigned long left;
+	void *ptr;
+	u32 calc;
+
+	for (addr = res->start; addr < res->end;
+	     addr += CHECK_CHUNKSIZE) {
+		left = res->end - addr;
+
+		if (left > CHECK_CHUNKSIZE)
+			left = CHECK_CHUNKSIZE;
+
+		ptr = phys_to_virt(addr);
+
+		if (in_region(ptr, left, crcs, crc_size)) {
+			DBG("skipping %08lx, has crc block in\n", addr);
+			goto skip_check;
+		}
+
+		if (in_region(ptr, left, save_at, 32*4 )) {
+			DBG("skipping %08lx, has save block in\n", addr);
+			goto skip_check;
+		}
+
+		/* calculate and check the checksum */
+
+		calc = crc32_le(~0, ptr, left);
+		if (calc != *val) {
+			printk(KERN_ERR PFX "Restore CRC error at "
+			       "%08lx (%08x vs %08x)\n", addr, calc, *val);
+
+			DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
+			    addr, calc, *val);
+		}
+
+	skip_check:
+		val++;
+	}
+
+	return val;
+}
+
+/* s3c2410_pm_check_restore
+ *
+ * check the CRCs after the restore event and free the memory used
+ * to hold them
+*/
+
+static void s3c2410_pm_check_restore(void)
+{
+	if (crcs != NULL) {
+		s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
+		kfree(crcs);
+		crcs = NULL;
+	}
+}
+
+#else
+
+#define s3c2410_pm_check_prepare() do { } while(0)
+#define s3c2410_pm_check_restore() do { } while(0)
+#define s3c2410_pm_check_store()   do { } while(0)
+#endif
+
+/* helper functions to save and restore register state */
+
+void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		ptr->val = __raw_readl(ptr->reg);
+		DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
+	}
+}
+
+/* s3c2410_pm_do_restore
+ *
+ * restore the system from the given list of saved registers
+ *
+ * Note, we do not use DBG() in here, as the system may not have
+ * restore the UARTs state yet
+*/
+
+void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
+		       ptr->reg, ptr->val, __raw_readl(ptr->reg));
+
+		__raw_writel(ptr->val, ptr->reg);
+	}
+}
+
+/* s3c2410_pm_do_restore_core
+ *
+ * similar to s3c2410_pm_do_restore_core
+ *
+ * WARNING: Do not put any debug in here that may effect memory or use
+ * peripherals, as things may be changing!
+*/
+
+static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
+{
+	for (; count > 0; count--, ptr++) {
+		__raw_writel(ptr->val, ptr->reg);
+	}
+}
+
+/* s3c2410_pm_show_resume_irqs
+ *
+ * print any IRQs asserted at resume time (ie, we woke from)
+*/
+
+static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
+					unsigned long mask)
+{
+	int i;
+
+	which &= ~mask;
+
+	for (i = 0; i <= 31; i++) {
+		if ((which) & (1L<<i)) {
+			DBG("IRQ %d asserted at resume\n", start+i);
+		}
+	}
+}
+
+/* s3c2410_pm_check_resume_pin
+ *
+ * check to see if the pin is configured correctly for sleep mode, and
+ * make any necessary adjustments if it is not
+*/
+
+static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
+{
+	unsigned long irqstate;
+	unsigned long pinstate;
+	int irq = s3c2410_gpio_getirq(pin);
+
+	if (irqoffs < 4)
+		irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
+	else
+		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
+
+	pinstate = s3c2410_gpio_getcfg(pin);
+
+	if (!irqstate) {
+		if (pinstate == S3C2410_GPIO_IRQ)
+			DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
+	} else {
+		if (pinstate == S3C2410_GPIO_IRQ) {
+			DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
+			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
+		}
+	}
+}
+
+/* s3c2410_pm_configure_extint
+ *
+ * configure all external interrupt pins
+*/
+
+static void s3c2410_pm_configure_extint(void)
+{
+	int pin;
+
+	/* for each of the external interrupts (EINT0..EINT15) we
+	 * need to check wether it is an external interrupt source,
+	 * and then configure it as an input if it is not
+	*/
+
+	for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
+		s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
+	}
+
+	for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
+		s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
+	}
+}
+
+void (*pm_cpu_prep)(void);
+void (*pm_cpu_sleep)(void);
+
+#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
+
+/* s3c2410_pm_enter
+ *
+ * central control for sleep/resume process
+*/
+
+static int s3c2410_pm_enter(suspend_state_t state)
+{
+	unsigned long regs_save[16];
+
+	/* ensure the debug is initialised (if enabled) */
+
+	s3c2410_pm_debug_init();
+
+	DBG("s3c2410_pm_enter(%d)\n", state);
+
+	if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
+		printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
+		return -EINVAL;
+	}
+
+	if (state != PM_SUSPEND_MEM) {
+		printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
+		return -EINVAL;
+	}
+
+	/* check if we have anything to wake-up with... bad things seem
+	 * to happen if you suspend with no wakeup (system will often
+	 * require a full power-cycle)
+	*/
+
+	if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
+	    !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
+		printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
+		printk(KERN_ERR PFX "Aborting sleep\n");
+		return -EINVAL;
+	}
+
+	/* prepare check area if configured */
+
+	s3c2410_pm_check_prepare();
+
+	/* store the physical address of the register recovery block */
+
+	s3c2410_sleep_save_phys = virt_to_phys(regs_save);
+
+	DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
+
+	/* save all necessary core registers not covered by the drivers */
+
+	s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
+	s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
+	s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
+
+	/* set the irq configuration for wake */
+
+	s3c2410_pm_configure_extint();
+
+	DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
+	    s3c_irqwake_intmask, s3c_irqwake_eintmask);
+
+	__raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
+	__raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
+
+	/* ack any outstanding external interrupts before we go to sleep */
+
+	__raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
+	__raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
+	__raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
+
+	/* call cpu specific preperation */
+
+	pm_cpu_prep();
+
+	/* flush cache back to ram */
+
+	flush_cache_all();
+
+	s3c2410_pm_check_store();
+
+	/* send the cpu to sleep... */
+
+	__raw_writel(0x00, S3C2410_CLKCON);  /* turn off clocks over sleep */
+
+	/* s3c2410_cpu_save will also act as our return point from when
+	 * we resume as it saves its own register state, so use the return
+	 * code to differentiate return from save and return from sleep */
+
+	if (s3c2410_cpu_save(regs_save) == 0) {
+		flush_cache_all();
+		pm_cpu_sleep();
+	}
+
+	/* restore the cpu state */
+
+	cpu_init();
+
+	/* restore the system state */
+
+	s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
+	s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
+	s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
+
+	s3c2410_pm_debug_init();
+
+	/* check what irq (if any) restored the system */
+
+	DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
+	    __raw_readl(S3C2410_SRCPND),
+	    __raw_readl(S3C2410_EINTPEND));
+
+	s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
+				    s3c_irqwake_intmask);
+
+	s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
+				    s3c_irqwake_eintmask);
+
+	DBG("post sleep, preparing to return\n");
+
+	s3c2410_pm_check_restore();
+
+	/* ok, let's return from sleep */
+
+	DBG("S3C2410 PM Resume (post-restore)\n");
+	return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int s3c2410_pm_prepare(suspend_state_t state)
+{
+	return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int s3c2410_pm_finish(suspend_state_t state)
+{
+	return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops s3c2410_pm_ops = {
+	.pm_disk_mode	= PM_DISK_FIRMWARE,
+	.prepare	= s3c2410_pm_prepare,
+	.enter		= s3c2410_pm_enter,
+	.finish		= s3c2410_pm_finish,
+};
+
+/* s3c2410_pm_init
+ *
+ * Attach the power management functions. This should be called
+ * from the board specific initialisation if the board supports
+ * it.
+*/
+
+int __init s3c2410_pm_init(void)
+{
+	printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
+
+	pm_set_ops(&s3c2410_pm_ops);
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/plat-s3c24xx/s3c244x-irq.c
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c244x-irq.c
rename to arch/arm/plat-s3c24xx/s3c244x-irq.c
index ede9463..a0e39d8 100644
--- a/arch/arm/mach-s3c2410/s3c244x-irq.c
+++ b/arch/arm/plat-s3c24xx/s3c244x-irq.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x-irq.c
+/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
  *
  * Copyright (c) 2003,2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
-#include "cpu.h"
-#include "pm.h"
-#include "irq.h"
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
+#include <asm/plat-s3c24xx/irq.h>
 
 /* camera irq */
 
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c244x.c
rename to arch/arm/plat-s3c24xx/s3c244x.c
index 23c7494..87aace4 100644
--- a/arch/arm/mach-s3c2410/s3c244x.c
+++ b/arch/arm/plat-s3c24xx/s3c244x.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/s3c244x.c
+/* linux/arch/arm/plat-s3c24xx/s3c244x.c
  *
  * Copyright (c) 2004-2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
@@ -35,13 +35,13 @@
 #include <asm/arch/regs-gpioj.h>
 #include <asm/arch/regs-dsc.h>
 
-#include "s3c2410.h"
-#include "s3c2440.h"
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/s3c2440.h>
 #include "s3c244x.h"
-#include "clock.h"
-#include "devs.h"
-#include "cpu.h"
-#include "pm.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/devs.h>
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
 static struct map_desc s3c244x_iodesc[] __initdata = {
 	IODESC_ENT(CLKPWR),
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/plat-s3c24xx/s3c244x.h
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c244x.h
rename to arch/arm/plat-s3c24xx/s3c244x.h
index 1488c1e..f8ed176 100644
--- a/arch/arm/mach-s3c2410/s3c244x.h
+++ b/arch/arm/plat-s3c24xx/s3c244x.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c244x.h
+/* linux/arch/arm/plat-s3c24xx/s3c244x.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
new file mode 100644
index 0000000..2018c2e
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -0,0 +1,159 @@
+/* linux/arch/arm/mach-s3c2410/sleep.S
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410 Power Manager (Suspend-To-RAM) support
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *	Cliff Brake, (c) 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+#include <asm/arch/map.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-serial.h>
+
+/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
+ * reset the UART configuration, only enable if you really need this!
+*/
+//#define CONFIG_DEBUG_RESUME
+
+	.text
+
+	/* s3c2410_cpu_save
+	 *
+	 * save enough of the CPU state to allow us to re-start
+	 * pm.c code. as we store items like the sp/lr, we will
+	 * end up returning from this function when the cpu resumes
+	 * so the return value is set to mark this.
+	 *
+	 * This arangement means we avoid having to flush the cache
+	 * from this code.
+	 *
+	 * entry:
+	 *	r0 = pointer to save block
+	 *
+	 * exit:
+	 *	r0 = 0 => we stored everything
+	 *	     1 => resumed from sleep
+	*/
+
+ENTRY(s3c2410_cpu_save)
+	stmfd	sp!, { r4 - r12, lr }
+
+	@@ store co-processor registers
+
+	mrc	p15, 0, r4, c15, c1, 0	@ CP access register
+	mrc	p15, 0, r5, c13, c0, 0	@ PID
+	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r7, c2, c0, 0	@ translation table base address
+	mrc	p15, 0, r8, c1, c0, 0	@ control register
+
+	stmia	r0, { r4 - r13 }
+
+	mov	r0, #0
+	ldmfd	sp, { r4 - r12, pc }
+
+	@@ return to the caller, after having the MMU
+	@@ turned on, this restores the last bits from the
+	@@ stack
+resume_with_mmu:
+	mov	r0, #1
+	ldmfd	sp!, { r4 - r12, pc }
+
+	.ltorg
+
+	@@ the next bits sit in the .data segment, even though they
+	@@ happen to be code... the s3c2410_sleep_save_phys needs to be
+	@@ accessed by the resume code before it can restore the MMU.
+	@@ This means that the variable has to be close enough for the
+	@@ code to read it... since the .text segment needs to be RO,
+	@@ the data segment can be the only place to put this code.
+
+	.data
+
+	.global	s3c2410_sleep_save_phys
+s3c2410_sleep_save_phys:
+	.word	0
+
+	/* s3c2410_cpu_resume
+	 *
+	 * resume code entry for bootloader to call
+	 *
+	 * we must put this code here in the data segment as we have no
+	 * other way of restoring the stack pointer after sleep, and we
+	 * must not write to the code segment (code is read-only)
+	*/
+
+ENTRY(s3c2410_cpu_resume)
+	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+	msr	cpsr_c, r0
+
+	@@ load UART to allow us to print the two characters for
+	@@ resume debug
+
+	mov	r2, #S3C24XX_PA_UART & 0xff000000
+	orr	r2, r2, #S3C24XX_PA_UART & 0xff000
+
+#if 0
+	/* SMDK2440 LED set */
+	mov	r14, #S3C24XX_PA_GPIO
+	ldr	r12, [ r14, #0x54 ]
+	bic	r12, r12, #3<<4
+	orr	r12, r12, #1<<7
+	str	r12, [ r14, #0x54 ]
+#endif
+
+#ifdef CONFIG_DEBUG_RESUME
+	mov	r3, #'L'
+	strb	r3, [ r2, #S3C2410_UTXH ]
+1001:
+	ldrb	r14, [ r3, #S3C2410_UTRSTAT ]
+	tst	r14, #S3C2410_UTRSTAT_TXE
+	beq	1001b
+#endif /* CONFIG_DEBUG_RESUME */
+
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
+
+	ldr	r0, s3c2410_sleep_save_phys	@ address of restore block
+	ldmia	r0, { r4 - r13 }
+
+	mcr	p15, 0, r4, c15, c1, 0		@ CP access register
+	mcr	p15, 0, r5, c13, c0, 0		@ PID
+	mcr	p15, 0, r6, c3, c0, 0		@ Domain ID
+	mcr	p15, 0, r7, c2, c0, 0		@ translation table base
+
+#ifdef CONFIG_DEBUG_RESUME
+	mov	r3, #'R'
+	strb	r3, [ r2, #S3C2410_UTXH ]
+#endif
+
+	ldr	r2, =resume_with_mmu
+	mcr	p15, 0, r8, c1, c0, 0		@ turn on MMU, etc
+	nop					@ second-to-last before mmu
+	mov	pc, r2				@ go back to virtual address
+
+	.ltorg
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/plat-s3c24xx/time.c
similarity index 98%
rename from arch/arm/mach-s3c2410/time.c
rename to arch/arm/plat-s3c24xx/time.c
index 9910bf0..c523d1c 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/time.c
+/* linux/arch/arm/plat-s3c24xx/time.c
  *
  * Copyright (C) 2003-2005 Simtec Electronics
  *	Ben Dooks, <ben@simtec.co.uk>
@@ -37,8 +37,8 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/mach/time.h>
 
-#include "clock.h"
-#include "cpu.h"
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
 static unsigned long timer_startval;
 static unsigned long timer_usec_ticks;
diff --git a/arch/arm/mach-s3c2410/clock.h b/include/asm-arm/plat-s3c24xx/clock.h
similarity index 96%
rename from arch/arm/mach-s3c2410/clock.h
rename to include/asm-arm/plat-s3c24xx/clock.h
index 7f0ea03..f6135db 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/include/asm-arm/plat-s3c24xx/clock.h
@@ -1,4 +1,4 @@
-/*
+/* linux/include/asm-arm/plat-s3c24xx/clock.h
  * linux/arch/arm/mach-s3c2410/clock.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/include/asm-arm/plat-s3c24xx/common-smdk.h
similarity index 88%
rename from arch/arm/mach-s3c2410/common-smdk.h
rename to include/asm-arm/plat-s3c24xx/common-smdk.h
index 0e3a3be..58d9094 100644
--- a/arch/arm/mach-s3c2410/common-smdk.h
+++ b/include/asm-arm/plat-s3c24xx/common-smdk.h
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/common-smdk.h
+/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/cpu.h b/include/asm-arm/plat-s3c24xx/cpu.h
similarity index 97%
rename from arch/arm/mach-s3c2410/cpu.h
rename to include/asm-arm/plat-s3c24xx/cpu.h
index be42e40..8181b22 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/include/asm-arm/plat-s3c24xx/cpu.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/cpu.h
+/* linux/include/asm-arm/plat-s3c24xx/cpu.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
similarity index 96%
rename from arch/arm/mach-s3c2410/devs.h
rename to include/asm-arm/plat-s3c24xx/devs.h
index 14fb0ba..dddf485 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/include/asm-arm/plat-s3c24xx/devs.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/devs.h
+/* linux/include/asm-arm/plat-s3c24xx/devs.h
  *
  * Copyright (c) 2004 Simtec Electronics
  * Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/dma.h b/include/asm-arm/plat-s3c24xx/dma.h
similarity index 95%
rename from arch/arm/mach-s3c2410/dma.h
rename to include/asm-arm/plat-s3c24xx/dma.h
index 0ebfe0a..421b567 100644
--- a/arch/arm/mach-s3c2410/dma.h
+++ b/include/asm-arm/plat-s3c24xx/dma.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/dma.h
+/* linux/include/asm-arm/plat-s3c24xx/dma.h
  *
  * Copyright (C) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
similarity index 97%
rename from arch/arm/mach-s3c2410/irq.h
rename to include/asm-arm/plat-s3c24xx/irq.h
index e5913da..8af6d95 100644
--- a/arch/arm/mach-s3c2410/irq.h
+++ b/include/asm-arm/plat-s3c24xx/irq.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/irq.h
+/* linux/include/asm-arm/plat-s3c24xx/irq.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/pm.h b/include/asm-arm/plat-s3c24xx/pm.h
similarity index 96%
rename from arch/arm/mach-s3c2410/pm.h
rename to include/asm-arm/plat-s3c24xx/pm.h
index ffe197a..cc62366 100644
--- a/arch/arm/mach-s3c2410/pm.h
+++ b/include/asm-arm/plat-s3c24xx/pm.h
@@ -1,4 +1,4 @@
-/* linux/arch/arm/mach-s3c2410/pm.h
+/* linux/include/asm-arm/plat-s3c24xx/pm.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Written by Ben Dooks, <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/include/asm-arm/plat-s3c24xx/s3c2400.h
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c2400.h
rename to include/asm-arm/plat-s3c24xx/s3c2400.h
index 8b2394e..3a5a168 100644
--- a/arch/arm/mach-s3c2410/s3c2400.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2400.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2400.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/include/asm-arm/plat-s3c24xx/s3c2410.h
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c2410.h
rename to include/asm-arm/plat-s3c24xx/s3c2410.h
index fbed084..36de0b8 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2410.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2410.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
  *
  * Copyright (c) 2004 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/include/asm-arm/plat-s3c24xx/s3c2412.h
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c2412.h
rename to include/asm-arm/plat-s3c24xx/s3c2412.h
index c6e5603..3ec9768 100644
--- a/arch/arm/mach-s3c2410/s3c2412.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2412.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2412.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/include/asm-arm/plat-s3c24xx/s3c2440.h
similarity index 89%
rename from arch/arm/mach-s3c2410/s3c2440.h
rename to include/asm-arm/plat-s3c24xx/s3c2440.h
index dcd3160..107853b 100644
--- a/arch/arm/mach-s3c2410/s3c2440.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2440.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2440.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2440.h
  *
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/include/asm-arm/plat-s3c24xx/s3c2442.h
similarity index 89%
rename from arch/arm/mach-s3c2410/s3c2442.h
rename to include/asm-arm/plat-s3c24xx/s3c2442.h
index 0ae37d2..451a23a 100644
--- a/arch/arm/mach-s3c2410/s3c2442.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2442.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-s3c2410/s3c2442.h
+/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
  *
  * Copyright (c) 2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>