]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
[ARM] 4157/2: S3C24XX: move arch/arch/mach-s3c2410 into cpu components
authorBen Dooks <ben-linux@fluff.org>
Sun, 11 Feb 2007 17:31:01 +0000 (18:31 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 11 Feb 2007 17:36:09 +0000 (17:36 +0000)
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>
83 files changed:
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/mach-s3c2400/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2400/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2400/gpio.c [moved from arch/arm/mach-s3c2410/s3c2400-gpio.c with 96% similarity]
arch/arm/mach-s3c2410/Kconfig
arch/arm/mach-s3c2410/Makefile
arch/arm/mach-s3c2410/bast-irq.c
arch/arm/mach-s3c2410/bast.h
arch/arm/mach-s3c2410/clock.c
arch/arm/mach-s3c2410/dma.c
arch/arm/mach-s3c2410/gpio.c
arch/arm/mach-s3c2410/irq.c
arch/arm/mach-s3c2410/mach-amlm5900.c
arch/arm/mach-s3c2410/mach-bast.c
arch/arm/mach-s3c2410/mach-h1940.c
arch/arm/mach-s3c2410/mach-n30.c
arch/arm/mach-s3c2410/mach-otom.c
arch/arm/mach-s3c2410/mach-smdk2410.c
arch/arm/mach-s3c2410/mach-vr1000.c
arch/arm/mach-s3c2410/pm.c
arch/arm/mach-s3c2410/s3c2410-clock.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-dma.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-gpio.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-irq.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-pm.c [deleted file]
arch/arm/mach-s3c2410/s3c2410-sleep.S [deleted file]
arch/arm/mach-s3c2410/s3c2410.c
arch/arm/mach-s3c2410/sleep.S
arch/arm/mach-s3c2410/usb-simtec.c
arch/arm/mach-s3c2412/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2412/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2412/clock.c [moved from arch/arm/mach-s3c2410/s3c2412-clock.c with 99% similarity]
arch/arm/mach-s3c2412/dma.c [moved from arch/arm/mach-s3c2410/s3c2412-dma.c with 97% similarity]
arch/arm/mach-s3c2412/irq.c [moved from arch/arm/mach-s3c2410/s3c2412-irq.c with 96% similarity]
arch/arm/mach-s3c2412/mach-smdk2413.c [moved from arch/arm/mach-s3c2410/mach-smdk2413.c with 92% similarity]
arch/arm/mach-s3c2412/mach-vstms.c [moved from arch/arm/mach-s3c2410/mach-vstms.c with 93% similarity]
arch/arm/mach-s3c2412/pm.c [moved from arch/arm/mach-s3c2410/s3c2412-pm.c with 95% similarity]
arch/arm/mach-s3c2412/s3c2412.c [moved from arch/arm/mach-s3c2410/s3c2412.c with 95% similarity]
arch/arm/mach-s3c2440/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2440/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2440/clock.c [moved from arch/arm/mach-s3c2410/s3c2440-clock.c with 97% similarity]
arch/arm/mach-s3c2440/dma.c [moved from arch/arm/mach-s3c2410/s3c2440-dma.c with 97% similarity]
arch/arm/mach-s3c2440/dsc.c [moved from arch/arm/mach-s3c2410/s3c2440-dsc.c with 91% similarity]
arch/arm/mach-s3c2440/irq.c [moved from arch/arm/mach-s3c2410/s3c2440-irq.c with 95% similarity]
arch/arm/mach-s3c2440/mach-anubis.c [moved from arch/arm/mach-s3c2410/mach-anubis.c with 98% similarity]
arch/arm/mach-s3c2440/mach-nexcoder.c [moved from arch/arm/mach-s3c2410/mach-nexcoder.c with 94% similarity]
arch/arm/mach-s3c2440/mach-osiris.c [moved from arch/arm/mach-s3c2410/mach-osiris.c with 97% similarity]
arch/arm/mach-s3c2440/mach-rx3715.c [moved from arch/arm/mach-s3c2410/mach-rx3715.c with 96% similarity]
arch/arm/mach-s3c2440/mach-smdk2440.c [moved from arch/arm/mach-s3c2410/mach-smdk2440.c with 94% similarity]
arch/arm/mach-s3c2440/s3c2440.c [moved from arch/arm/mach-s3c2410/s3c2440.c with 88% similarity]
arch/arm/mach-s3c2442/Kconfig [new file with mode: 0644]
arch/arm/mach-s3c2442/Makefile [new file with mode: 0644]
arch/arm/mach-s3c2442/clock.c [moved from arch/arm/mach-s3c2410/s3c2442-clock.c with 97% similarity]
arch/arm/mach-s3c2442/s3c2442.c [moved from arch/arm/mach-s3c2410/s3c2442.c with 86% similarity]
arch/arm/plat-s3c24xx/Kconfig [new file with mode: 0644]
arch/arm/plat-s3c24xx/Makefile [new file with mode: 0644]
arch/arm/plat-s3c24xx/clock.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/common-smdk.c [moved from arch/arm/mach-s3c2410/common-smdk.c with 96% similarity]
arch/arm/plat-s3c24xx/cpu.c [moved from arch/arm/mach-s3c2410/cpu.c with 96% similarity]
arch/arm/plat-s3c24xx/devs.c [moved from arch/arm/mach-s3c2410/devs.c with 99% similarity]
arch/arm/plat-s3c24xx/dma.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/gpio.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/irq.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/pm-simtec.c [moved from arch/arm/mach-s3c2410/pm-simtec.c with 95% similarity]
arch/arm/plat-s3c24xx/pm.c [new file with mode: 0644]
arch/arm/plat-s3c24xx/s3c244x-irq.c [moved from arch/arm/mach-s3c2410/s3c244x-irq.c with 95% similarity]
arch/arm/plat-s3c24xx/s3c244x.c [moved from arch/arm/mach-s3c2410/s3c244x.c with 94% similarity]
arch/arm/plat-s3c24xx/s3c244x.h [moved from arch/arm/mach-s3c2410/s3c244x.h with 94% similarity]
arch/arm/plat-s3c24xx/sleep.S [new file with mode: 0644]
arch/arm/plat-s3c24xx/time.c [moved from arch/arm/mach-s3c2410/time.c with 98% similarity]
include/asm-arm/plat-s3c24xx/clock.h [moved from arch/arm/mach-s3c2410/clock.h with 97% similarity]
include/asm-arm/plat-s3c24xx/common-smdk.h [moved from arch/arm/mach-s3c2410/common-smdk.h with 88% similarity]
include/asm-arm/plat-s3c24xx/cpu.h [moved from arch/arm/mach-s3c2410/cpu.h with 97% similarity]
include/asm-arm/plat-s3c24xx/devs.h [moved from arch/arm/mach-s3c2410/devs.h with 97% similarity]
include/asm-arm/plat-s3c24xx/dma.h [moved from arch/arm/mach-s3c2410/dma.h with 96% similarity]
include/asm-arm/plat-s3c24xx/irq.h [moved from arch/arm/mach-s3c2410/irq.h with 98% similarity]
include/asm-arm/plat-s3c24xx/pm.h [moved from arch/arm/mach-s3c2410/pm.h with 97% similarity]
include/asm-arm/plat-s3c24xx/s3c2400.h [moved from arch/arm/mach-s3c2410/s3c2400.h with 94% similarity]
include/asm-arm/plat-s3c24xx/s3c2410.h [moved from arch/arm/mach-s3c2410/s3c2410.h with 93% similarity]
include/asm-arm/plat-s3c24xx/s3c2412.h [moved from arch/arm/mach-s3c2410/s3c2412.h with 93% similarity]
include/asm-arm/plat-s3c24xx/s3c2440.h [moved from arch/arm/mach-s3c2410/s3c2440.h with 89% similarity]
include/asm-arm/plat-s3c24xx/s3c2442.h [moved from arch/arm/mach-s3c2410/s3c2442.h with 89% similarity]

index 6783c2e5512de6e75bed91d55a45ff0c14ee0cf5..51ee13e7c74ccf65009a930b198c5325a0c454d4 100644 (file)
@@ -363,7 +363,15 @@ source "arch/arm/mach-omap1/Kconfig"
 
 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"
 
index 000f1100b5538f9f69da886fc0054d2d16746864..2df1ea0a0c2d1985d3b6889c7779482bfc55a38b 100644 (file)
@@ -149,7 +149,7 @@ MACHINE  := arch/arm/mach-$(machine-y)/
 else
 MACHINE  :=
 endif
-  
+
 export TEXT_OFFSET GZFLAGS MMUEXT
 
 # Do we have FASTFPE?
@@ -161,6 +161,10 @@ endif
 # 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 @@ core-$(CONFIG_VFP)          += arch/arm/vfp/
 # 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 (file)
index 0000000..deab072
--- /dev/null
@@ -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 (file)
index 0000000..7e23f4e
--- /dev/null
@@ -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
+
similarity index 96%
rename from arch/arm/mach-s3c2410/s3c2400-gpio.c
rename to arch/arm/mach-s3c2400/gpio.c
index 1576d01d5f829bb31ec78ec2976acf6e3443f41e..758e160410e95f2f77724f108022119a79a0c357 100644 (file)
@@ -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>
  *
index 0ab590ec45822cd54b6ed5a7d853004b56a2e79d..016b53f5d6fc9673e1ab5f1246e608679882c157 100644 (file)
@@ -1,54 +1,51 @@
-if ARCH_S3C2410
+# arch/arm/mach-s3c2410/Kconfig
+#
+# Copyright 2007 Simtec Electronics
+#
+# Licensed under GPLv2
 
-menu "S3C24XX Implementations"
+config CPU_S3C2410
+       bool
+       depends on ARCH_S3C2410
+       select S3C2410_CLOCK
+       select S3C2410_GPIO
+       select S3C2410_PM if PM
+       help
+         Support for S3C2410 and S3C2410A family from the S3C24XX line
+         of Samsung Mobile CPUs.
 
-config MACH_AML_M5900
-       bool "AML M5900 Series"
-       select CPU_S3C2410
-       select PM_SIMTEC if PM
+config CPU_S3C2410_DMA
+       bool
+       depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
+       default y if CPU_S3C2410 || CPU_S3C2442
        help
-          Say Y here if you are using the American Microsystems M5900 Series
-           <http://www.amltd.com>
+         DMA device selection for S3C2410 and compatible CPUs
 
-config MACH_ANUBIS
-       bool "Simtec Electronics ANUBIS"
-       select CPU_S3C2440
-       select PM_SIMTEC if PM
+config S3C2410_PM
+       bool
        help
-         Say Y here if you are using the Simtec Electronics ANUBIS
-         development system
+         Power Management code common to S3C2410 and better
 
-config MACH_OSIRIS
-       bool "Simtec IM2440D20 (OSIRIS) module"
-       select CPU_S3C2440
-       select PM_SIMTEC if PM
+config S3C2410_GPIO
+       bool
        help
-         Say Y here if you are using the Simtec IM2440D20 module, also
-         known as the Osiris.
+         GPIO code for S3C2410 and similar processors
 
-config ARCH_BAST
-       bool "Simtec Electronics BAST (EB2410ITX)"
-       select CPU_S3C2410
-       select PM_SIMTEC if PM
-       select ISA
+config S3C2410_CLOCK
+       bool
        help
-         Say Y here if you are using the Simtec Electronics EB2410ITX
-         development board (also known as BAST)
+         Clock code for the S3C2410, and similar processors
 
-         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)
+menu "S3C2410 Machines"
 
-config PM_H1940
-       bool
+config ARCH_SMDK2410
+       bool "SMDK2410/A9M2410"
+       select CPU_S3C2410
+       select MACH_SMDK
        help
-         Internal node for H1940 and related PM
+          Say Y here if you are using the SMDK2410 or the derived module A9M2410
+           <http://www.fsforth.de>
 
 config ARCH_H1940
        bool "IPAQ H1940"
@@ -57,7 +54,10 @@ config ARCH_H1940
        help
          Say Y here if you are using the HP IPAQ H1940
 
-         <http://www.handhelds.org/projects/h1940.html>.
+config PM_H1940
+       bool
+       help
+         Internal node for H1940 and related PM
 
 config MACH_N30
        bool "Acer N30"
@@ -65,53 +65,36 @@ config MACH_N30
        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"
+config ARCH_BAST
+       bool "Simtec Electronics BAST (EB2410ITX)"
        select CPU_S3C2410
-       select MACH_SMDK
+       select PM_SIMTEC if PM
+       select ISA
        help
-          Say Y here if you are using the SMDK2410 or the derived module A9M2410
-           <http://www.fsforth.de>
+         Say Y here if you are using the Simtec Electronics EB2410ITX
+         development board (also known as BAST)
 
-config ARCH_S3C2440
-       bool "SMDK2440"
-       select CPU_S3C2440
-       select MACH_SMDK
+config MACH_OTOM
+       bool "NexVision OTOM Board"
+       select CPU_S3C2410
        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
+         Say Y here if you are using the Nex Vision OTOM board
 
-config MACH_S3C2413
-       bool
+config MACH_AML_M5900
+       bool "AML M5900 Series"
+       select CPU_S3C2410
+       select PM_SIMTEC if PM
        help
-         Internal node for S3C2413 version of SMDK2413, so that
-         machine_is_s3c2413() will work when MACH_SMDK2413 is
-         selected
+          Say Y here if you are using the American Microsystems M5900 Series
+           <http://www.amltd.com>
 
-config MACH_SMDK2413
-       bool "SMDK2413"
-       select CPU_S3C2412
-       select MACH_S3C2413
-       select MACH_SMDK
+config BAST_PC104_IRQ
+       bool "BAST PC104 IRQ support"
+       depends on ARCH_BAST
+       default y
        help
-         Say Y here if you are using an SMDK2413
+         Say Y here to enable the PC104 IRQ routing on the
+         Simtec BAST (EB2410ITX)
 
 config MACH_VR1000
        bool "Thorcom VR1000"
@@ -120,223 +103,6 @@ config MACH_VR1000
        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
-
-config CPU_S3C2410
-       bool
-       depends on ARCH_S3C2410
-       select S3C2410_CLOCK
-       select S3C2410_GPIO
-       select S3C2410_PM if PM
-       help
-         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
-       bool
-       depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
-                  !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
-       default y if CPU_S3C2412
-
-config S3C2412_PM
-       bool
-       help
-         Internal config node to apply S3C2412 power management
-
-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
-       bool
-       help
-         Common power management code for systems that are
-         compatible with the Simtec style of power management
-
-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.
-
-         Note, this does not affect the port used by the debug messages,
-         which is a separate configuration.
-
-endif
index 1cc5febdaabdbc7076aec71ea5d52057c15f3dcd..b33ac5b8477331552decdfd4245a0c405db55ec9 100644 (file)
@@ -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_S3C2410_PM)       += s3c2410-pm.o s3c2410-sleep.o
-obj-$(CONFIG_S3C2410_GPIO)     += s3c2410-gpio.o
-obj-$(CONFIG_CPU_S3C2410_DMA)  += s3c2410-dma.o
-
-# 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_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_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
+# Machine support
 
-# 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_SMDK2410)    += mach-smdk2410.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_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_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
index 379efe70778c6841d4b407d16b3a33c5f66070b5..daeba427d781bf9868396db7811941101e163c82 100644 (file)
@@ -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>
index e5d03311752c06b4965c0c123112769f0b5ea1f4..e98543742eb936ae17da100530d63bf510999b5b 100644 (file)
@@ -1,2 +1,2 @@
-
+/* linux/arch/arm/mach-s3c2410/bast.h
 extern void bast_init_irq(void);
index e13fb6778890d6559f2a57e532cf16f4cf13dd38..5b4831c4c1d8dccb556c35a6502c92b238933672 100644 (file)
@@ -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
 #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"
-
-/* clock information */
+#include <asm/plat-s3c24xx/s3c2410.h>
+#include <asm/plat-s3c24xx/clock.h>
+#include <asm/plat-s3c24xx/cpu.h>
 
-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;
-}
-
-/* Clock API calls */
+       unsigned int clocks = clk->ctrlbit;
+       unsigned long clkcon;
 
-struct clk *clk_get(struct device *dev, const char *id)
-{
-       struct clk *p;
-       struct clk *clk = ERR_PTR(-ENOENT);
-       int idno;
+       clkcon = __raw_readl(S3C2410_CLKCON);
 
-       if (dev == NULL || dev->bus != &platform_bus_type)
-               idno = -1;
+       if (enable)
+               clkcon |= clocks;
        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;
-                       }
-               }
-       }
+               clkcon &= ~clocks;
 
-       mutex_unlock(&clocks_mutex);
-       return clk;
-}
+       /* ensure none of the special function bits set */
+       clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
 
-void clk_put(struct clk *clk)
-{
-       module_put(clk->owner);
-}
+       __raw_writel(clkcon, S3C2410_CLKCON);
 
-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)
+static int s3c2410_upll_enable(struct clk *clk, int enable)
 {
-       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);
+       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+       unsigned long orig = clkslow;
 
        if (enable)
-               dclkcon |= clk->ctrlbit;
+               clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
        else
-               dclkcon &= ~clk->ctrlbit;
+               clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
 
-       __raw_writel(dclkcon, S3C24XX_DCLKCON);
+       __raw_writel(clkslow, S3C2410_CLKSLOW);
 
-       return 0;
-}
+       /* if we started the UPLL, then allow to settle */
 
-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);
+       if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+               udelay(200);
 
        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;
+/* 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,
        }
-
-       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,
+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,
+       },
 };
 
-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 */
+/* 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 s3c24xx_setup_clocks(unsigned long xtal,
-                               unsigned long fclk,
-                               unsigned long hclk,
-                               unsigned long pclk)
+int __init s3c2410_baseclk_add(void)
 {
-       printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
+       unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+       unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+       struct clk *clkp;
+       struct clk *xtal;
+       int ret;
+       int ptr;
 
-       /* initialise the main system clocks */
+       clk_upll.enable = s3c2410_upll_enable;
 
-       clk_xtal.rate = xtal;
-       clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
+       if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+               printk(KERN_ERR "failed to register usb bus clock\n");
 
-       clk_mpll.rate = fclk;
-       clk_h.rate = hclk;
-       clk_p.rate = pclk;
-       clk_f.rate = fclk;
+       /* register clocks from clock array */
 
-       /* assume uart clocks are correctly setup */
+       clkp = init_clocks;
+       for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+               /* ensure that we note the clock state */
 
-       /* register our clocks */
+               clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
 
-       if (s3c24xx_register_clock(&clk_xtal) < 0)
-               printk(KERN_ERR "failed to register master xtal\n");
+               ret = s3c24xx_register_clock(clkp);
+               if (ret < 0) {
+                       printk(KERN_ERR "Failed to register clock %s (%d)\n",
+                              clkp->name, ret);
+               }
+       }
 
-       if (s3c24xx_register_clock(&clk_mpll) < 0)
-               printk(KERN_ERR "failed to register mpll clock\n");
+       /* 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);
+               }
 
-       if (s3c24xx_register_clock(&clk_upll) < 0)
-               printk(KERN_ERR "failed to register upll clock\n");
+               s3c2410_clkcon_enable(clkp, 0);
+       }
 
-       if (s3c24xx_register_clock(&clk_f) < 0)
-               printk(KERN_ERR "failed to register cpu fclk\n");
+       /* show the clock-slow value */
 
-       if (s3c24xx_register_clock(&clk_h) < 0)
-               printk(KERN_ERR "failed to register cpu hclk\n");
+       xtal = clk_get(NULL, "xtal");
 
-       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;
 }
index fa860e716b4ff74e5af753a81ae3a2c8152b3e30..22c613600caad5cb301fd1e8a63ae4864fc4f615 100644 (file)
@@ -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/
  *
  * 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/mach/dma.h>
-#include <asm/arch/map.h>
-
-#include "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;
+#include <asm/arch/dma.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>
+#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,
+       },
 };
 
-#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)
+static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
+                              struct s3c24xx_dma_map *map)
 {
-       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;
+       chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
 }
 
-/* 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.
-*/
+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),
+};
 
-int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
+static int s3c2410_dma_add(struct sys_device *sysdev)
 {
-       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;
+       return s3c24xx_dma_init_map(&s3c2410_dma_sel);
 }
 
-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;
-}
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_dma_driver = {
+       .add    = s3c2410_dma_add,
+};
 
-void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+static int __init s3c2410_dma_init(void)
 {
-       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);
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
 }
 
-
-/* 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);
-       }
+arch_initcall(s3c2410_dma_init);
 #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,
+#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,
 };
 
-/* 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)
+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.
-*/
-
-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);
+arch_initcall(s3c2442_dma_init);
+#endif
 
-       return 0;
-}
index f6fb215bb48c2a7d6f5dc108cc1ffe70ccd532c3..01e795d1146eec85691ff1d1f41495e94108a5bf 100644 (file)
@@ -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>
 
 #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)
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+                          unsigned int config)
 {
-       void __iomem *base = S3C24XX_GPIO_BASE(pin);
-       unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+       void __iomem *reg = S3C24XX_EINFLT0;
        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);
+       unsigned long val;
 
-       local_irq_restore(flags);
-}
+       if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+               return -1;
 
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
+       config &= 0xff;
 
-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;
+       pin -= S3C2410_GPG8;
+       reg += pin & ~3;
 
        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);
+       /* update filter width and clock source */
 
-       return __raw_readl(base + 0x04) & (1<< offs);
-}
+       val = __raw_readl(reg);
+       val &= ~(0xff << ((pin & 3) * 8));
+       val |= config << ((pin & 3) * 8);
+       __raw_writel(val, reg);
 
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
+       /* update filter enable */
 
-unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
-{
-       unsigned long flags;
-       unsigned long misccr;
+       val = __raw_readl(S3C24XX_EXTINT2);
+       val &= ~(1 << ((pin * 4) + 3));
+       val |= on << ((pin * 4) + 3);
+       __raw_writel(val, S3C24XX_EXTINT2);
 
-       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;
+       return 0;
 }
 
-EXPORT_SYMBOL(s3c2410_gpio_getirq);
+EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
index 3c0ed7871c55dc51c0c4dbf41a7a0d4e92fbb70f..53cbdaa43ac666a0d4ab5f2e05531c71910095ea 100644 (file)
@@ -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
  * 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/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 "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)
-{
-       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;
+#include <asm/plat-s3c24xx/cpu.h>
+#include <asm/plat-s3c24xx/pm.h>
 
-       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)
+static int s3c2410_irq_add(struct sys_device *sysdev)
 {
-       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),
+static struct sysdev_driver s3c2410_irq_driver = {
+       .add            = s3c2410_irq_add,
+       .suspend        = s3c24xx_irq_suspend,
+       .resume         = s3c24xx_irq_resume,
 };
 
-/* 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)
+static int s3c2410_irq_init(void)
 {
-       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;
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
 }
 
-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);
index 817e2c684410bce25eeae0d383f296bad14cb644..d54cda1b3006e01e67de71997c39baf7f30d99ac 100644 (file)
@@ -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
 
index b8b76757ec54a70272a9107b06f5b554a50d299f..7b81296427ebc54ce28cc519575e57e23eb58a95 100644 (file)
@@ -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"
index 15b625eae499e2e13b0d3e61dea07a7963347520..5af26e177966d42a603a4c618ae88fa82e91f00f 100644 (file)
 #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] = {
index 0411e9adb54d9b208682d849859a5dd16c97f08d..dbac7311f98f53ff2c2ef458ff25c3c2363cda4d 100644 (file)
 #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 */
index 2c738b375e4d6da64359154ea3f0073f6e6a2ea9..c78ab75b44f30cb33d198e4ba455baadd4af5aa2 100644 (file)
 #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 */
index 01c0c986d827de5d12f775aaf4abce49a7bd988e..57b8a80f33d0c53c2672d72c496b88255add8072 100644 (file)
@@ -1,4 +1,4 @@
-/***********************************************************************
+/* linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
  * linux/arch/arm/mach-s3c2410/mach-smdk2410.c
  *
 
 #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 */
index a382fc095110ec21b9b07563a0b140893e40db98..c947c75bcbf0f982f13566db3a0fe61b45ea7eb5 100644 (file)
@@ -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 */
index ebf294dd31da7cf25410ac4327f58a230833a1b9..3b3a7db4e0dd961028ad43869fc22f5e6a2d365e 100644 (file)
@@ -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
  * 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/arch/regs-gpio.h>
-#include <asm/arch/regs-mem.h>
-#include <asm/arch/regs-irq.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),
+#include <asm/mach-types.h>
 
-       SAVE_ITEM(S3C2410_GPGCON),
-       SAVE_ITEM(S3C2410_GPGDAT),
-       SAVE_ITEM(S3C2410_GPGUP),
-
-       SAVE_ITEM(S3C2410_GPHCON),
-       SAVE_ITEM(S3C2410_GPHDAT),
-       SAVE_ITEM(S3C2410_GPHUP),
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/h1940.h>
 
-       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)
-{
-       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)
+static void s3c2410_pm_prepare(void)
 {
-       crc_size = 0;
+       /* ensure at least GSTATUS3 has the resume address */
 
-       s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
+       __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
 
-       DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
+       DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
+       DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
 
-       crcs = kmalloc(crc_size+4, GFP_KERNEL);
-       if (crcs == NULL)
-               printk(KERN_ERR "Cannot allocated CRC save area\n");
-}
+       if (machine_is_h1940()) {
+               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+               unsigned long ptr;
+               unsigned long calc = 0;
 
-static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
-{
-       unsigned long addr, left;
+               /* generate check for the bootloader to check on resume */
 
-       for (addr = res->start; addr < res->end;
-            addr += CHECK_CHUNKSIZE) {
-               left = res->end - addr;
+               for (ptr = 0; ptr < 0x40000; ptr += 0x400)
+                       calc += __raw_readl(base+ptr);
 
-               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;
-}
-
-/* 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;
+       /* the RX3715 uses similar code and the same H1940 and the
+        * same offsets for resume and checksum pointers */
 
-               if (left > CHECK_CHUNKSIZE)
-                       left = CHECK_CHUNKSIZE;
+       if (machine_is_rx3715()) {
+               void *base = phys_to_virt(H1940_SUSPEND_CHECK);
+               unsigned long ptr;
+               unsigned long calc = 0;
 
-               ptr = phys_to_virt(addr);
+               /* generate check for the bootloader to check on resume */
 
-               if (in_region(ptr, left, crcs, crc_size)) {
-                       DBG("skipping %08lx, has crc block in\n", addr);
-                       goto skip_check;
-               }
+               for (ptr = 0; ptr < 0x40000; ptr += 0x4)
+                       calc += __raw_readl(base+ptr);
 
-               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++;
+               __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
        }
 
-       return val;
-}
+       if ( machine_is_aml_m5900() )
+               s3c2410_gpio_setpin(S3C2410_GPF2, 1);
 
-/* 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)
+static int s3c2410_pm_resume(struct sys_device *dev)
 {
-       for (; count > 0; count--, ptr++) {
-               ptr->val = __raw_readl(ptr->reg);
-               DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
-       }
-}
+       unsigned long tmp;
 
-/* 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
-*/
+       /* unset the return-from-sleep flag, to ensure reset */
 
-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);
-       }
-}
+       tmp = __raw_readl(S3C2410_GSTATUS2);
+       tmp &= S3C2410_GSTATUS2_OFFRESET;
+       __raw_writel(tmp, S3C2410_GSTATUS2);
 
-/* 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!
-*/
+       if ( machine_is_aml_m5900() )
+               s3c2410_gpio_setpin(S3C2410_GPF2, 0);
 
-static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
-{
-       for (; count > 0; count--, ptr++) {
-               __raw_writel(ptr->val, ptr->reg);
-       }
+       return 0;
 }
 
-/* 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)
+static int s3c2410_pm_add(struct sys_device *dev)
 {
-       int i;
+       pm_cpu_prep = s3c2410_pm_prepare;
+       pm_cpu_sleep = s3c2410_cpu_suspend;
 
-       which &= ~mask;
-
-       for (i = 0; i <= 31; i++) {
-               if ((which) & (1L<<i)) {
-                       DBG("IRQ %d asserted at resume\n", start+i);
-               }
-       }
+       return 0;
 }
 
-/* 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);
-               }
-       }
-}
+#if defined(CONFIG_CPU_S3C2410)
+static struct sysdev_driver s3c2410_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
+};
 
-/* s3c2410_pm_configure_extint
- *
- * configure all external interrupt pins
-*/
+/* register ourselves */
 
-static void s3c2410_pm_configure_extint(void)
+static int __init s3c2410_pm_drvinit(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);
-       }
+       return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
 }
 
-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 */
+arch_initcall(s3c2410_pm_drvinit);
+#endif
 
-       DBG("S3C2410 PM Resume (post-restore)\n");
-       return 0;
-}
+#if defined(CONFIG_CPU_S3C2440)
+static struct sysdev_driver s3c2440_pm_driver = {
+       .add            = s3c2410_pm_add,
+       .resume         = s3c2410_pm_resume,
+};
 
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-static int s3c2410_pm_prepare(suspend_state_t state)
+static int __init s3c2440_pm_drvinit(void)
 {
-       return 0;
+       return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
 }
 
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-static int s3c2410_pm_finish(suspend_state_t state)
-{
-       return 0;
-}
+arch_initcall(s3c2440_pm_drvinit);
+#endif
 
-/*
- * 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_S3C2442)
+static struct sysdev_driver s3c2442_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.
-*/
-
-int __init s3c2410_pm_init(void)
+static int __init s3c2442_pm_drvinit(void)
 {
-       printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
-
-       pm_set_ops(&s3c2410_pm_ops);
-       return 0;
+       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 (file)
index 992cc6a..0000000
+++ /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 (file)
index e67ba39..0000000
+++ /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 (file)
index ec3a276..0000000
+++ /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 (file)
index c796c9c..0000000
+++ /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 (file)
index 8bb6e5e..0000000
+++ /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 (file)
index 9179a10..0000000
+++ /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
index 4cdc0d70c19f3fa6203440a6ea2f3082575c9861..d96fdcf2d2e33a535156421e7ead2f139e31583e 100644 (file)
 #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 */
 
index 2018c2e1dcc5aecc97a9c9ec1825fc3c6b2fc29c..9179a1024588359b32bb58158a5f6bc1caeaf9b5 100644 (file)
@@ -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>
 #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
+       /* s3c2410_cpu_suspend
         *
-        * 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)
+        * put the cpu into sleep mode
        */
 
-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
+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
index 22b0e1cdd4bf3d4e584588b4399c54646c673847..bcd562ac1d3da4899dca3b73ac3e9184e6c2d55e 100644 (file)
@@ -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 (file)
index 0000000..6d629de
--- /dev/null
@@ -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 (file)
index 0000000..f8e0116
--- /dev/null
@@ -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
similarity index 99%
rename from arch/arm/mach-s3c2410/s3c2412-clock.c
rename to arch/arm/mach-s3c2412/clock.c
index 8f94ad83901db64ed762ba6c2c400cc8d12d1937..6a8e4448770bdce38870138b780db90477932bcf 100644 (file)
@@ -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
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2412-dma.c
rename to arch/arm/mach-s3c2412/dma.c
index 138f726ac6bfa8efcbd38bae070fb83ee5ecee40..28b598287fae444e60cae91a2a44162abadee537 100644 (file)
@@ -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>
similarity index 96%
rename from arch/arm/mach-s3c2410/s3c2412-irq.c
rename to arch/arm/mach-s3c2412/irq.c
index ffcc30b23a8052d1a0abf920b4cdeed0ad203f9e..e89dbdcb1b7bf70c68d8a3b8288a69dd2ad80cd9 100644 (file)
@@ -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
similarity index 92%
rename from arch/arm/mach-s3c2410/mach-smdk2413.c
rename to arch/arm/mach-s3c2412/mach-smdk2413.c
index 4f89abd7a6dfcd03a58365e562fe205b73414618..32b15617ef2ae519b8c5aa634ef610b8988d070a 100644 (file)
@@ -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>
 #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 = {
 };
similarity index 93%
rename from arch/arm/mach-s3c2410/mach-vstms.c
rename to arch/arm/mach-s3c2412/mach-vstms.c
index 0360e1055bcd7485e1b6f8e0cfee40310644e4c4..f1afb707ff1627cabe57332eadf40dcbf337b6aa 100644 (file)
@@ -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>
  *
 
 #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 = {
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2412-pm.c
rename to arch/arm/mach-s3c2412/pm.c
index 19b63322d2592c32404b23acb194f2c40c3f4feb..8988dac388a9cf83e3182f4aac1a0d19c3431f29 100644 (file)
@@ -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>
 #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)
 {
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2412.c
rename to arch/arm/mach-s3c2412/s3c2412.c
index 2f651a811ecd5f6c513a5731274192ba28c03673..aafe0bc593f17bb92f8e32c0b82391c260bf0a7d 100644 (file)
@@ -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>
 #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 (file)
index 0000000..e3bfda0
--- /dev/null
@@ -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 (file)
index 0000000..c81ed62
--- /dev/null
@@ -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
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2440-clock.c
rename to arch/arm/mach-s3c2440/clock.c
index ba13c1d079d100c9b4759b6c89039bd46cf782b5..79e2ea4adaf36defb9b1f863c1a0444146d2a9e0 100644 (file)
@@ -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 */
 
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2440-dma.c
rename to arch/arm/mach-s3c2440/dma.c
index 47b861b9443d7d0a864e0f3d367987e8c0e251de..8e51137620f2252b0e422fe3081df677b5a1f7d9 100644 (file)
@@ -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>
similarity index 91%
rename from arch/arm/mach-s3c2410/s3c2440-dsc.c
rename to arch/arm/mach-s3c2440/dsc.c
index c92ea66ba45e5599b99d59efae967268630a5046..2995ff5681bbde83f82c1ee065950d6611959bf5 100644 (file)
@@ -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)
 {
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c2440-irq.c
rename to arch/arm/mach-s3c2440/irq.c
index 1ba19b27ab0560c18bde1709aad224de3d47fc0a..1069d13d8c5792732871471c228e025f13a029a6 100644 (file)
@@ -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 */
 
similarity index 98%
rename from arch/arm/mach-s3c2410/mach-anubis.c
rename to arch/arm/mach-s3c2440/mach-anubis.c
index 0fad0c2fe07b3b33d72b5d92dc2f0629dddd6934..3f0288eb1ed5c9e69abbfee77e1c489f2125daba 100644 (file)
@@ -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"
 
similarity index 94%
rename from arch/arm/mach-s3c2410/mach-nexcoder.c
rename to arch/arm/mach-s3c2440/mach-nexcoder.c
index d6dfdad8c90bbdd9d4d442dd0c64ec40086c510a..6d551d88330b4b48af834cd84a01f88b01c05690 100644 (file)
@@ -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>
 #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 */
similarity index 97%
rename from arch/arm/mach-s3c2410/mach-osiris.c
rename to arch/arm/mach-s3c2440/mach-osiris.c
index 37b40850c9b9006d9caeef435fc2a08ce24ee4a6..2ed8e51f20c8525378ced153896b11e080db0cbe 100644 (file)
@@ -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 */
 
similarity index 96%
rename from arch/arm/mach-s3c2410/mach-rx3715.c
rename to arch/arm/mach-s3c2440/mach-rx3715.c
index ecbcdf79d739b9abf1f4f5e248aca5292a412e39..1d4e19bd920620f85685fd5ad84dcb89899aec70 100644 (file)
@@ -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>
 #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 */
similarity index 94%
rename from arch/arm/mach-s3c2410/mach-smdk2440.c
rename to arch/arm/mach-s3c2440/mach-smdk2440.c
index 2b61f4ed1da410fa21449d3ce95af14c80b0c005..270e42b9b5c10954ff4e2bb61fc8c21903450cb0 100644 (file)
@@ -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>
 #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) */
similarity index 88%
rename from arch/arm/mach-s3c2410/s3c2440.c
rename to arch/arm/mach-s3c2440/s3c2440.c
index 344eb27cca48cf7ecb8138431348bf6d46d03c15..90e1da61fbc3641b0f4d90045e138c4e09bc8c00 100644 (file)
@@ -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 (file)
index 0000000..bf8d87a
--- /dev/null
@@ -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 (file)
index 0000000..2a909c6
--- /dev/null
@@ -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
+
similarity index 97%
rename from arch/arm/mach-s3c2410/s3c2442-clock.c
rename to arch/arm/mach-s3c2442/clock.c
index 4e292ca7c9be7f7731fffe76ee2a1c358384546c..5b9e830ac4d30a337529ad5e3609e786932f5954 100644 (file)
@@ -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 */
 
similarity index 86%
rename from arch/arm/mach-s3c2410/s3c2442.c
rename to arch/arm/mach-s3c2442/s3c2442.c
index 428732ee68c41520c4cf4acb72ff4b5f6d11c166..fbf8264249da376879221f29e82b08a4138657e3 100644 (file)
@@ -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 (file)
index 0000000..9781364
--- /dev/null
@@ -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 (file)
index 0000000..8e5ccaa
--- /dev/null
@@ -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 (file)
index 0000000..d3dc03a
--- /dev/null
@@ -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;
+}
similarity index 96%
rename from arch/arm/mach-s3c2410/common-smdk.c
rename to arch/arm/plat-s3c24xx/common-smdk.c
index a40eaa6561771bbd3c09410b9e06b6e1cc6967de..908efa7d745fbc98fea12ecd38079e3dcd41dbaf 100644 (file)
@@ -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 */
 
similarity index 96%
rename from arch/arm/mach-s3c2410/cpu.c
rename to arch/arm/plat-s3c24xx/cpu.c
index ae1f5bb63f7a809081a31a437aa983b944c66fa1..2fbb74969379563e5020936997bf90075fa194f4 100644 (file)
@@ -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/
 #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;
similarity index 99%
rename from arch/arm/mach-s3c2410/devs.c
rename to arch/arm/plat-s3c24xx/devs.c
index faccde2092d2f353617e61893218c50a263ab22c..6d46c4e2a4f77e6bde831570f1b942406ae77b06 100644 (file)
@@ -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 (file)
index 0000000..c784e1f
--- /dev/null
@@ -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 (file)
index 0000000..ec3a09c
--- /dev/null
@@ -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 (file)
index 0000000..ce18639
--- /dev/null
@@ -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");
+}
similarity index 95%
rename from arch/arm/mach-s3c2410/pm-simtec.c
rename to arch/arm/plat-s3c24xx/pm-simtec.c
index 619133eb716802b9002c6b44022591f44b80cddd..bd965f2feecae51e053dba07f04d697707546c31 100644 (file)
@@ -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 (file)
index 0000000..ecf68d6
--- /dev/null
@@ -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;
+}
similarity index 95%
rename from arch/arm/mach-s3c2410/s3c244x-irq.c
rename to arch/arm/plat-s3c24xx/s3c244x-irq.c
index ede94636a72a94bc0be668fd102472b5975d8ca2..a0e39d894014278274d1a9b4ed2e70e70ff5d914 100644 (file)
@@ -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 */
 
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c244x.c
rename to arch/arm/plat-s3c24xx/s3c244x.c
index 23c7494ad10d57ce685de8e74da04c74da6a9261..87aace4c8f8cdfafb56b9bf3a2f6faefbbeb17e1 100644 (file)
@@ -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>
 #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),
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c244x.h
rename to arch/arm/plat-s3c24xx/s3c244x.h
index 1488c1eb37e67cf56c4c929d6722e1d5af3610e8..f8ed17676a355c49a7f5af03818cdc826a85df10 100644 (file)
@@ -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 (file)
index 0000000..2018c2e
--- /dev/null
@@ -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
similarity index 98%
rename from arch/arm/mach-s3c2410/time.c
rename to arch/arm/plat-s3c24xx/time.c
index 9910bf0f2cea63c3fab5e53e79a9a6398762b418..c523d1c9cce5e6e4c2ae0723aca5c3dc5871cd22 100644 (file)
@@ -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;
similarity index 97%
rename from arch/arm/mach-s3c2410/clock.h
rename to include/asm-arm/plat-s3c24xx/clock.h
index 7f0ea03e1d49398df37f5e843982b769635dd583..f6135dbb9fa9601db1358979b1b0c6bc5033ec78 100644 (file)
@@ -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
similarity index 88%
rename from arch/arm/mach-s3c2410/common-smdk.h
rename to include/asm-arm/plat-s3c24xx/common-smdk.h
index 0e3a3be330a3455f001d426d99be021cfd21e575..58d9094c935c05b7ab71f5d74a507b7d241ca739 100644 (file)
@@ -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>
similarity index 97%
rename from arch/arm/mach-s3c2410/cpu.h
rename to include/asm-arm/plat-s3c24xx/cpu.h
index be42e4032a6d670f3004ae550b88ac923400d284..8181b22532bd8e1380f54add378d9cec23cf4680 100644 (file)
@@ -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>
similarity index 97%
rename from arch/arm/mach-s3c2410/devs.h
rename to include/asm-arm/plat-s3c24xx/devs.h
index 14fb0bade7165c68057eeb1cda6b03a353d2a176..dddf485fc0670fe4833b7fc5e57f282fb7df4223 100644 (file)
@@ -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>
similarity index 96%
rename from arch/arm/mach-s3c2410/dma.h
rename to include/asm-arm/plat-s3c24xx/dma.h
index 0ebfe0aab80be885bd256e6677793c19ce12be0b..421b567fa0195642584a606b19a8e15cc653b380 100644 (file)
@@ -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>
similarity index 98%
rename from arch/arm/mach-s3c2410/irq.h
rename to include/asm-arm/plat-s3c24xx/irq.h
index e5913da3b919bb3ffbffbbf48a94c129b6e8d243..8af6d9579b31c975bd86ca6e2e6c1c2ed62ab4f9 100644 (file)
@@ -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>
similarity index 97%
rename from arch/arm/mach-s3c2410/pm.h
rename to include/asm-arm/plat-s3c24xx/pm.h
index ffe197a119fb096b2e3c1d9c6788094946011fcc..cc623667e48a4585a11145a50ec40e1207239a42 100644 (file)
@@ -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>
similarity index 94%
rename from arch/arm/mach-s3c2410/s3c2400.h
rename to include/asm-arm/plat-s3c24xx/s3c2400.h
index 8b2394e1ed4088c3b8d38e87e58bde2f38152bf7..3a5a16821af8e5de6cbdcd3c3719847ff39d072a 100644 (file)
@@ -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>
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c2410.h
rename to include/asm-arm/plat-s3c24xx/s3c2410.h
index fbed084f26d049116f58673383507583f815b5a7..36de0b8358737794c0fdcc2e53c58cab7cb56718 100644 (file)
@@ -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>
similarity index 93%
rename from arch/arm/mach-s3c2410/s3c2412.h
rename to include/asm-arm/plat-s3c24xx/s3c2412.h
index c6e56032a6e7177336ce06de58cce2d71b0967e3..3ec97685e7819029c342b0571a541db22c470cd1 100644 (file)
@@ -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>
similarity index 89%
rename from arch/arm/mach-s3c2410/s3c2440.h
rename to include/asm-arm/plat-s3c24xx/s3c2440.h
index dcd316076c595e3c1c014d7d64a59f95dd20669c..107853bf94813f14a72402ce2789176c1600d66d 100644 (file)
@@ -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>
similarity index 89%
rename from arch/arm/mach-s3c2410/s3c2442.h
rename to include/asm-arm/plat-s3c24xx/s3c2442.h
index 0ae37d24866cd4f9393cdca4e77faa4e36ad4bf8..451a23a2092aa98fb8d582f47b3141621f760eaf 100644 (file)
@@ -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>