aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig28
-rw-r--r--arch/arm/Makefile8
-rw-r--r--arch/arm/boot/.gitignore2
-rw-r--r--arch/arm/boot/compressed/.gitignore1
-rw-r--r--arch/arm/common/dmabounce.c87
-rw-r--r--arch/arm/common/gic.c109
-rw-r--r--arch/arm/configs/at91sam9263ek_defconfig1184
-rw-r--r--arch/arm/configs/ateb9200_defconfig2
-rw-r--r--arch/arm/configs/csb337_defconfig8
-rw-r--r--arch/arm/configs/csb637_defconfig6
-rw-r--r--arch/arm/configs/kafa_defconfig2
-rw-r--r--arch/arm/configs/s3c2410_defconfig142
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/calls.S1
-rw-r--r--arch/arm/kernel/crunch.c1
-rw-r--r--arch/arm/kernel/ecard.c2
-rw-r--r--arch/arm/kernel/machine_kexec.c78
-rw-r--r--arch/arm/kernel/relocate_kernel.S74
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/kernel/time.c4
-rw-r--r--arch/arm/mach-at91/Kconfig (renamed from arch/arm/mach-at91rm9200/Kconfig)39
-rw-r--r--arch/arm/mach-at91/Makefile (renamed from arch/arm/mach-at91rm9200/Makefile)4
-rw-r--r--arch/arm/mach-at91/Makefile.boot (renamed from arch/arm/mach-at91rm9200/Makefile.boot)0
-rw-r--r--arch/arm/mach-at91/at91rm9200.c (renamed from arch/arm/mach-at91rm9200/at91rm9200.c)39
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c (renamed from arch/arm/mach-at91rm9200/at91rm9200_devices.c)10
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c (renamed from arch/arm/mach-at91rm9200/at91rm9200_time.c)2
-rw-r--r--arch/arm/mach-at91/at91sam9260.c (renamed from arch/arm/mach-at91rm9200/at91sam9260.c)90
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c (renamed from arch/arm/mach-at91rm9200/at91sam9260_devices.c)16
-rw-r--r--arch/arm/mach-at91/at91sam9261.c (renamed from arch/arm/mach-at91rm9200/at91sam9261.c)23
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c (renamed from arch/arm/mach-at91rm9200/at91sam9261_devices.c)10
-rw-r--r--arch/arm/mach-at91/at91sam9263.c313
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c818
-rw-r--r--arch/arm/mach-at91/at91sam926x_time.c (renamed from arch/arm/mach-at91rm9200/at91sam926x_time.c)5
-rw-r--r--arch/arm/mach-at91/board-1arm.c (renamed from arch/arm/mach-at91rm9200/board-1arm.c)2
-rw-r--r--arch/arm/mach-at91/board-carmeva.c (renamed from arch/arm/mach-at91rm9200/board-carmeva.c)4
-rw-r--r--arch/arm/mach-at91/board-csb337.c (renamed from arch/arm/mach-at91rm9200/board-csb337.c)43
-rw-r--r--arch/arm/mach-at91/board-csb637.c (renamed from arch/arm/mach-at91rm9200/board-csb637.c)41
-rw-r--r--arch/arm/mach-at91/board-dk.c (renamed from arch/arm/mach-at91rm9200/board-dk.c)4
-rw-r--r--arch/arm/mach-at91/board-eb9200.c (renamed from arch/arm/mach-at91rm9200/board-eb9200.c)4
-rw-r--r--arch/arm/mach-at91/board-ek.c (renamed from arch/arm/mach-at91rm9200/board-ek.c)4
-rw-r--r--arch/arm/mach-at91/board-kafa.c (renamed from arch/arm/mach-at91rm9200/board-kafa.c)2
-rw-r--r--arch/arm/mach-at91/board-kb9202.c (renamed from arch/arm/mach-at91rm9200/board-kb9202.c)4
-rw-r--r--arch/arm/mach-at91/board-sam9260ek.c (renamed from arch/arm/mach-at91rm9200/board-sam9260ek.c)6
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c (renamed from arch/arm/mach-at91rm9200/board-sam9261ek.c)4
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c176
-rw-r--r--arch/arm/mach-at91/clock.c (renamed from arch/arm/mach-at91rm9200/clock.c)64
-rw-r--r--arch/arm/mach-at91/clock.h (renamed from arch/arm/mach-at91rm9200/clock.h)2
-rw-r--r--arch/arm/mach-at91/generic.h (renamed from arch/arm/mach-at91rm9200/generic.h)4
-rw-r--r--arch/arm/mach-at91/gpio.c (renamed from arch/arm/mach-at91rm9200/gpio.c)2
-rw-r--r--arch/arm/mach-at91/irq.c (renamed from arch/arm/mach-at91rm9200/irq.c)2
-rw-r--r--arch/arm/mach-at91/leds.c (renamed from arch/arm/mach-at91rm9200/leds.c)4
-rw-r--r--arch/arm/mach-at91/pm.c (renamed from arch/arm/mach-at91rm9200/pm.c)4
-rw-r--r--arch/arm/mach-ep93xx/clock.c6
-rw-r--r--arch/arm/mach-ep93xx/core.c115
-rw-r--r--arch/arm/mach-iop32x/n2100.c14
-rw-r--r--arch/arm/mach-pxa/generic.c24
-rw-r--r--arch/arm/mach-realview/Kconfig11
-rw-r--r--arch/arm/mach-realview/platsmp.c4
-rw-r--r--arch/arm/mach-realview/realview_eb.c38
-rw-r--r--arch/arm/mach-s3c2400/Kconfig13
-rw-r--r--arch/arm/mach-s3c2400/Makefile15
-rw-r--r--arch/arm/mach-s3c2400/gpio.c (renamed from arch/arm/mach-s3c2410/s3c2400-gpio.c)2
-rw-r--r--arch/arm/mach-s3c2410/Kconfig338
-rw-r--r--arch/arm/mach-s3c2410/Makefile103
-rw-r--r--arch/arm/mach-s3c2410/bast-irq.c2
-rw-r--r--arch/arm/mach-s3c2410/bast.h2
-rw-r--r--arch/arm/mach-s3c2410/clock.c565
-rw-r--r--arch/arm/mach-s3c2410/clock.h63
-rw-r--r--arch/arm/mach-s3c2410/common-smdk.h15
-rw-r--r--arch/arm/mach-s3c2410/cpu.h69
-rw-r--r--arch/arm/mach-s3c2410/devs.h51
-rw-r--r--arch/arm/mach-s3c2410/dma.c1546
-rw-r--r--arch/arm/mach-s3c2410/dma.h45
-rw-r--r--arch/arm/mach-s3c2410/gpio.c165
-rw-r--r--arch/arm/mach-s3c2410/irq.c775
-rw-r--r--arch/arm/mach-s3c2410/irq.h107
-rw-r--r--arch/arm/mach-s3c2410/mach-amlm5900.c14
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c6
-rw-r--r--arch/arm/mach-s3c2410/mach-h1940.c64
-rw-r--r--arch/arm/mach-s3c2410/mach-n30.c9
-rw-r--r--arch/arm/mach-s3c2410/mach-otom.c8
-rw-r--r--arch/arm/mach-s3c2410/mach-qt2410.c448
-rw-r--r--arch/arm/mach-s3c2410/mach-smdk2410.c8
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c6
-rw-r--r--arch/arm/mach-s3c2410/pm.c653
-rw-r--r--arch/arm/mach-s3c2410/pm.h73
-rw-r--r--arch/arm/mach-s3c2410/s3c2400.h31
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-clock.c276
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-dma.c161
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-gpio.c71
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-irq.c48
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-pm.c156
-rw-r--r--arch/arm/mach-s3c2410/s3c2410-sleep.S68
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.c10
-rw-r--r--arch/arm/mach-s3c2410/s3c2410.h31
-rw-r--r--arch/arm/mach-s3c2410/s3c2412.h29
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.h17
-rw-r--r--arch/arm/mach-s3c2410/s3c2442.h17
-rw-r--r--arch/arm/mach-s3c2410/sleep.S151
-rw-r--r--arch/arm/mach-s3c2410/usb-simtec.c2
-rw-r--r--arch/arm/mach-s3c2412/Kconfig58
-rw-r--r--arch/arm/mach-s3c2412/Makefile21
-rw-r--r--arch/arm/mach-s3c2412/clock.c (renamed from arch/arm/mach-s3c2410/s3c2412-clock.c)8
-rw-r--r--arch/arm/mach-s3c2412/dma.c (renamed from arch/arm/mach-s3c2410/s3c2412-dma.c)7
-rw-r--r--arch/arm/mach-s3c2412/irq.c (renamed from arch/arm/mach-s3c2410/s3c2412-irq.c)8
-rw-r--r--arch/arm/mach-s3c2412/mach-smdk2413.c (renamed from arch/arm/mach-s3c2410/mach-smdk2413.c)68
-rw-r--r--arch/arm/mach-s3c2412/mach-vstms.c (renamed from arch/arm/mach-s3c2410/mach-vstms.c)13
-rw-r--r--arch/arm/mach-s3c2412/pm.c (renamed from arch/arm/mach-s3c2410/s3c2412-pm.c)8
-rw-r--r--arch/arm/mach-s3c2412/s3c2412.c (renamed from arch/arm/mach-s3c2410/s3c2412.c)12
-rw-r--r--arch/arm/mach-s3c2440/Kconfig71
-rw-r--r--arch/arm/mach-s3c2440/Makefile23
-rw-r--r--arch/arm/mach-s3c2440/clock.c (renamed from arch/arm/mach-s3c2410/s3c2440-clock.c)6
-rw-r--r--arch/arm/mach-s3c2440/dma.c (renamed from arch/arm/mach-s3c2410/s3c2440-dma.c)51
-rw-r--r--arch/arm/mach-s3c2440/dsc.c (renamed from arch/arm/mach-s3c2410/s3c2440-dsc.c)6
-rw-r--r--arch/arm/mach-s3c2440/irq.c (renamed from arch/arm/mach-s3c2410/s3c2440-irq.c)8
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c (renamed from arch/arm/mach-s3c2410/mach-anubis.c)8
-rw-r--r--arch/arm/mach-s3c2440/mach-nexcoder.c (renamed from arch/arm/mach-s3c2410/mach-nexcoder.c)12
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c (renamed from arch/arm/mach-s3c2410/mach-osiris.c)8
-rw-r--r--arch/arm/mach-s3c2440/mach-rx3715.c (renamed from arch/arm/mach-s3c2410/mach-rx3715.c)11
-rw-r--r--arch/arm/mach-s3c2440/mach-smdk2440.c (renamed from arch/arm/mach-s3c2410/mach-smdk2440.c)17
-rw-r--r--arch/arm/mach-s3c2440/s3c2440.c (renamed from arch/arm/mach-s3c2410/s3c2440.c)8
-rw-r--r--arch/arm/mach-s3c2442/Kconfig27
-rw-r--r--arch/arm/mach-s3c2442/Makefile16
-rw-r--r--arch/arm/mach-s3c2442/clock.c (renamed from arch/arm/mach-s3c2410/s3c2442-clock.c)6
-rw-r--r--arch/arm/mach-s3c2442/s3c2442.c (renamed from arch/arm/mach-s3c2410/s3c2442.c)6
-rw-r--r--arch/arm/mach-s3c2443/Kconfig29
-rw-r--r--arch/arm/mach-s3c2443/Makefile20
-rw-r--r--arch/arm/mach-s3c2443/clock.c1007
-rw-r--r--arch/arm/mach-s3c2443/dma.c180
-rw-r--r--arch/arm/mach-s3c2443/irq.c290
-rw-r--r--arch/arm/mach-s3c2443/mach-smdk2443.c137
-rw-r--r--arch/arm/mach-s3c2443/s3c2443.c97
-rw-r--r--arch/arm/mm/Kconfig11
-rw-r--r--arch/arm/mm/Makefile2
-rw-r--r--arch/arm/mm/cache-l2x0.c104
-rw-r--r--arch/arm/mm/consistent.c17
-rw-r--r--arch/arm/mm/context.c12
-rw-r--r--arch/arm/mm/fault-armv.c2
-rw-r--r--arch/arm/mm/mmu.c3
-rw-r--r--arch/arm/mm/proc-v6.S22
-rw-r--r--arch/arm/mm/proc-xsc3.S151
-rw-r--r--arch/arm/mm/tlb-v6.S4
-rw-r--r--arch/arm/plat-s3c24xx/Kconfig99
-rw-r--r--arch/arm/plat-s3c24xx/Makefile30
-rw-r--r--arch/arm/plat-s3c24xx/clock.c449
-rw-r--r--arch/arm/plat-s3c24xx/common-smdk.c (renamed from arch/arm/mach-s3c2410/common-smdk.c)8
-rw-r--r--arch/arm/plat-s3c24xx/cpu.c (renamed from arch/arm/mach-s3c2410/cpu.c)29
-rw-r--r--arch/arm/plat-s3c24xx/devs.c (renamed from arch/arm/mach-s3c2410/devs.c)21
-rw-r--r--arch/arm/plat-s3c24xx/dma.c1499
-rw-r--r--arch/arm/plat-s3c24xx/gpio.c188
-rw-r--r--arch/arm/plat-s3c24xx/irq.c801
-rw-r--r--arch/arm/plat-s3c24xx/pm-simtec.c (renamed from arch/arm/mach-s3c2410/pm-simtec.c)4
-rw-r--r--arch/arm/plat-s3c24xx/pm.c659
-rw-r--r--arch/arm/plat-s3c24xx/s3c244x-irq.c (renamed from arch/arm/mach-s3c2410/s3c244x-irq.c)8
-rw-r--r--arch/arm/plat-s3c24xx/s3c244x.c (renamed from arch/arm/mach-s3c2410/s3c244x.c)16
-rw-r--r--arch/arm/plat-s3c24xx/s3c244x.h (renamed from arch/arm/mach-s3c2410/s3c244x.h)2
-rw-r--r--arch/arm/plat-s3c24xx/sleep.S157
-rw-r--r--arch/arm/plat-s3c24xx/time.c (renamed from arch/arm/mach-s3c2410/time.c)6
-rw-r--r--arch/avr32/mach-at32ap/clock.c2
-rw-r--r--arch/avr32/mach-at32ap/clock.h2
160 files changed, 10891 insertions, 5597 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c84350868c23..8136d32cd78f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -288,6 +288,7 @@ config ARCH_PXA
288 bool "PXA2xx-based" 288 bool "PXA2xx-based"
289 depends on MMU 289 depends on MMU
290 select ARCH_MTD_XIP 290 select ARCH_MTD_XIP
291 select GENERIC_TIME
291 help 292 help
292 Support for Intel's PXA2XX processor line. 293 Support for Intel's PXA2XX processor line.
293 294
@@ -311,7 +312,7 @@ config ARCH_SA1100
311 Support for StrongARM 11x0 based boards. 312 Support for StrongARM 11x0 based boards.
312 313
313config ARCH_S3C2410 314config ARCH_S3C2410
314 bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442" 315 bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
315 help 316 help
316 Samsung S3C2410X CPU based systems, such as the Simtec Electronics 317 Samsung S3C2410X CPU based systems, such as the Simtec Electronics
317 BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or 318 BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -371,7 +372,16 @@ source "arch/arm/mach-omap1/Kconfig"
371 372
372source "arch/arm/mach-omap2/Kconfig" 373source "arch/arm/mach-omap2/Kconfig"
373 374
375source "arch/arm/plat-s3c24xx/Kconfig"
376
377if ARCH_S3C2410
378source "arch/arm/mach-s3c2400/Kconfig"
374source "arch/arm/mach-s3c2410/Kconfig" 379source "arch/arm/mach-s3c2410/Kconfig"
380source "arch/arm/mach-s3c2412/Kconfig"
381source "arch/arm/mach-s3c2440/Kconfig"
382source "arch/arm/mach-s3c2442/Kconfig"
383source "arch/arm/mach-s3c2443/Kconfig"
384endif
375 385
376source "arch/arm/mach-lh7a40x/Kconfig" 386source "arch/arm/mach-lh7a40x/Kconfig"
377 387
@@ -385,7 +395,7 @@ source "arch/arm/mach-aaec2000/Kconfig"
385 395
386source "arch/arm/mach-realview/Kconfig" 396source "arch/arm/mach-realview/Kconfig"
387 397
388source "arch/arm/mach-at91rm9200/Kconfig" 398source "arch/arm/mach-at91/Kconfig"
389 399
390source "arch/arm/mach-netx/Kconfig" 400source "arch/arm/mach-netx/Kconfig"
391 401
@@ -748,6 +758,20 @@ config XIP_PHYS_ADDR
748 be linked for and stored to. This address is dependent on your 758 be linked for and stored to. This address is dependent on your
749 own flash usage. 759 own flash usage.
750 760
761config KEXEC
762 bool "Kexec system call (EXPERIMENTAL)"
763 depends on EXPERIMENTAL
764 help
765 kexec is a system call that implements the ability to shutdown your
766 current kernel, and to start another kernel. It is like a reboot
767 but it is indepedent of the system firmware. And like a reboot
768 you can start any kernel with it, not just Linux.
769
770 It is an ongoing process to be certain the hardware in a machine
771 is properly shutdown, so do not be surprised if this code does not
772 initially work for you. It may help to enable device hotplugging
773 support.
774
751endmenu 775endmenu
752 776
753if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX ) 777if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 52d119422293..1320418b5d6f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -151,7 +151,7 @@ MACHINE := arch/arm/mach-$(machine-y)/
151else 151else
152MACHINE := 152MACHINE :=
153endif 153endif
154 154
155export TEXT_OFFSET GZFLAGS MMUEXT 155export TEXT_OFFSET GZFLAGS MMUEXT
156 156
157# Do we have FASTFPE? 157# Do we have FASTFPE?
@@ -163,6 +163,11 @@ endif
163# If we have a machine-specific directory, then include it in the build. 163# If we have a machine-specific directory, then include it in the build.
164core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ 164core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
165core-y += $(MACHINE) 165core-y += $(MACHINE)
166core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2400/
167core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2412/
168core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2440/
169core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2442/
170core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2443/
166core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ 171core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
167core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) 172core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
168core-$(CONFIG_VFP) += arch/arm/vfp/ 173core-$(CONFIG_VFP) += arch/arm/vfp/
@@ -170,6 +175,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/
170# If we have a common platform directory, then include it in the build. 175# If we have a common platform directory, then include it in the build.
171core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/ 176core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/
172core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/ 177core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/
178core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/
173 179
174drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ 180drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
175drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ 181drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
new file mode 100644
index 000000000000..171a0853caf8
--- /dev/null
+++ b/arch/arm/boot/.gitignore
@@ -0,0 +1,2 @@
1Image
2zImage
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
new file mode 100644
index 000000000000..aefee20cbf98
--- /dev/null
+++ b/arch/arm/boot/compressed/.gitignore
@@ -0,0 +1 @@
piggy.gz
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 2e635b814c14..6fbe7722aa44 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -32,7 +32,6 @@
32 32
33#include <asm/cacheflush.h> 33#include <asm/cacheflush.h>
34 34
35#undef DEBUG
36#undef STATS 35#undef STATS
37 36
38#ifdef STATS 37#ifdef STATS
@@ -66,14 +65,13 @@ struct dmabounce_pool {
66}; 65};
67 66
68struct dmabounce_device_info { 67struct dmabounce_device_info {
69 struct list_head node;
70
71 struct device *dev; 68 struct device *dev;
72 struct list_head safe_buffers; 69 struct list_head safe_buffers;
73#ifdef STATS 70#ifdef STATS
74 unsigned long total_allocs; 71 unsigned long total_allocs;
75 unsigned long map_op_count; 72 unsigned long map_op_count;
76 unsigned long bounce_count; 73 unsigned long bounce_count;
74 int attr_res;
77#endif 75#endif
78 struct dmabounce_pool small; 76 struct dmabounce_pool small;
79 struct dmabounce_pool large; 77 struct dmabounce_pool large;
@@ -81,33 +79,23 @@ struct dmabounce_device_info {
81 rwlock_t lock; 79 rwlock_t lock;
82}; 80};
83 81
84static LIST_HEAD(dmabounce_devs);
85
86#ifdef STATS 82#ifdef STATS
87static void print_alloc_stats(struct dmabounce_device_info *device_info) 83static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
84 char *buf)
88{ 85{
89 printk(KERN_INFO 86 struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
90 "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n", 87 return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
91 device_info->dev->bus_id, 88 device_info->small.allocs,
92 device_info->small.allocs, device_info->large.allocs, 89 device_info->large.allocs,
93 device_info->total_allocs - device_info->small.allocs - 90 device_info->total_allocs - device_info->small.allocs -
94 device_info->large.allocs, 91 device_info->large.allocs,
95 device_info->total_allocs); 92 device_info->total_allocs,
93 device_info->map_op_count,
94 device_info->bounce_count);
96} 95}
97#endif
98
99/* find the given device in the dmabounce device list */
100static inline struct dmabounce_device_info *
101find_dmabounce_dev(struct device *dev)
102{
103 struct dmabounce_device_info *d;
104 96
105 list_for_each_entry(d, &dmabounce_devs, node) 97static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
106 if (d->dev == dev) 98#endif
107 return d;
108
109 return NULL;
110}
111 99
112 100
113/* allocate a 'safe' buffer and keep track of it */ 101/* allocate a 'safe' buffer and keep track of it */
@@ -162,8 +150,6 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
162 if (pool) 150 if (pool)
163 pool->allocs++; 151 pool->allocs++;
164 device_info->total_allocs++; 152 device_info->total_allocs++;
165 if (device_info->total_allocs % 1000 == 0)
166 print_alloc_stats(device_info);
167#endif 153#endif
168 154
169 write_lock_irqsave(&device_info->lock, flags); 155 write_lock_irqsave(&device_info->lock, flags);
@@ -218,20 +204,11 @@ free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *
218 204
219/* ************************************************** */ 205/* ************************************************** */
220 206
221#ifdef STATS
222static void print_map_stats(struct dmabounce_device_info *device_info)
223{
224 dev_info(device_info->dev,
225 "dmabounce: map_op_count=%lu, bounce_count=%lu\n",
226 device_info->map_op_count, device_info->bounce_count);
227}
228#endif
229
230static inline dma_addr_t 207static inline dma_addr_t
231map_single(struct device *dev, void *ptr, size_t size, 208map_single(struct device *dev, void *ptr, size_t size,
232 enum dma_data_direction dir) 209 enum dma_data_direction dir)
233{ 210{
234 struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); 211 struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
235 dma_addr_t dma_addr; 212 dma_addr_t dma_addr;
236 int needs_bounce = 0; 213 int needs_bounce = 0;
237 214
@@ -281,10 +258,14 @@ map_single(struct device *dev, void *ptr, size_t size,
281 ptr = buf->safe; 258 ptr = buf->safe;
282 259
283 dma_addr = buf->safe_dma_addr; 260 dma_addr = buf->safe_dma_addr;
261 } else {
262 /*
263 * We don't need to sync the DMA buffer since
264 * it was allocated via the coherent allocators.
265 */
266 consistent_sync(ptr, size, dir);
284 } 267 }
285 268
286 consistent_sync(ptr, size, dir);
287
288 return dma_addr; 269 return dma_addr;
289} 270}
290 271
@@ -292,7 +273,7 @@ static inline void
292unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, 273unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
293 enum dma_data_direction dir) 274 enum dma_data_direction dir)
294{ 275{
295 struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); 276 struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
296 struct safe_buffer *buf = NULL; 277 struct safe_buffer *buf = NULL;
297 278
298 /* 279 /*
@@ -317,12 +298,12 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
317 DO_STATS ( device_info->bounce_count++ ); 298 DO_STATS ( device_info->bounce_count++ );
318 299
319 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) { 300 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
320 unsigned long ptr; 301 void *ptr = buf->ptr;
321 302
322 dev_dbg(dev, 303 dev_dbg(dev,
323 "%s: copy back safe %p to unsafe %p size %d\n", 304 "%s: copy back safe %p to unsafe %p size %d\n",
324 __func__, buf->safe, buf->ptr, size); 305 __func__, buf->safe, ptr, size);
325 memcpy(buf->ptr, buf->safe, size); 306 memcpy(ptr, buf->safe, size);
326 307
327 /* 308 /*
328 * DMA buffers must have the same cache properties 309 * DMA buffers must have the same cache properties
@@ -332,8 +313,8 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
332 * bidirectional case because we know the cache 313 * bidirectional case because we know the cache
333 * lines will be coherent with the data written. 314 * lines will be coherent with the data written.
334 */ 315 */
335 ptr = (unsigned long)buf->ptr;
336 dmac_clean_range(ptr, ptr + size); 316 dmac_clean_range(ptr, ptr + size);
317 outer_clean_range(__pa(ptr), __pa(ptr) + size);
337 } 318 }
338 free_safe_buffer(device_info, buf); 319 free_safe_buffer(device_info, buf);
339 } 320 }
@@ -343,7 +324,7 @@ static inline void
343sync_single(struct device *dev, dma_addr_t dma_addr, size_t size, 324sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
344 enum dma_data_direction dir) 325 enum dma_data_direction dir)
345{ 326{
346 struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); 327 struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
347 struct safe_buffer *buf = NULL; 328 struct safe_buffer *buf = NULL;
348 329
349 if (device_info) 330 if (device_info)
@@ -397,7 +378,10 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
397 default: 378 default:
398 BUG(); 379 BUG();
399 } 380 }
400 consistent_sync(buf->safe, size, dir); 381 /*
382 * No need to sync the safe buffer - it was allocated
383 * via the coherent allocators.
384 */
401 } else { 385 } else {
402 consistent_sync(dma_to_virt(dev, dma_addr), size, dir); 386 consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
403 } 387 }
@@ -604,9 +588,10 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
604 device_info->total_allocs = 0; 588 device_info->total_allocs = 0;
605 device_info->map_op_count = 0; 589 device_info->map_op_count = 0;
606 device_info->bounce_count = 0; 590 device_info->bounce_count = 0;
591 device_info->attr_res = device_create_file(dev, &dev_attr_dmabounce_stats);
607#endif 592#endif
608 593
609 list_add(&device_info->node, &dmabounce_devs); 594 dev->archdata.dmabounce = device_info;
610 595
611 printk(KERN_INFO "dmabounce: registered device %s on %s bus\n", 596 printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
612 dev->bus_id, dev->bus->name); 597 dev->bus_id, dev->bus->name);
@@ -623,7 +608,9 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
623void 608void
624dmabounce_unregister_dev(struct device *dev) 609dmabounce_unregister_dev(struct device *dev)
625{ 610{
626 struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); 611 struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
612
613 dev->archdata.dmabounce = NULL;
627 614
628 if (!device_info) { 615 if (!device_info) {
629 printk(KERN_WARNING 616 printk(KERN_WARNING
@@ -645,12 +632,10 @@ dmabounce_unregister_dev(struct device *dev)
645 dma_pool_destroy(device_info->large.pool); 632 dma_pool_destroy(device_info->large.pool);
646 633
647#ifdef STATS 634#ifdef STATS
648 print_alloc_stats(device_info); 635 if (device_info->attr_res == 0)
649 print_map_stats(device_info); 636 device_remove_file(dev, &dev_attr_dmabounce_stats);
650#endif 637#endif
651 638
652 list_del(&device_info->node);
653
654 kfree(device_info); 639 kfree(device_info);
655 640
656 printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n", 641 printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 09b9d1b6844c..4deece5fbdf4 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -14,7 +14,9 @@
14 * 14 *
15 * o There is one CPU Interface per CPU, which sends interrupts sent 15 * o There is one CPU Interface per CPU, which sends interrupts sent
16 * by the Distributor, and interrupts generated locally, to the 16 * by the Distributor, and interrupts generated locally, to the
17 * associated CPU. 17 * associated CPU. The base address of the CPU interface is usually
18 * aliased so that the same address points to different chips depending
19 * on the CPU it is accessed from.
18 * 20 *
19 * Note that IRQs 0-31 are special - they are local to each CPU. 21 * Note that IRQs 0-31 are special - they are local to each CPU.
20 * As such, the enable set/clear, pending set/clear and active bit 22 * As such, the enable set/clear, pending set/clear and active bit
@@ -31,10 +33,38 @@
31#include <asm/mach/irq.h> 33#include <asm/mach/irq.h>
32#include <asm/hardware/gic.h> 34#include <asm/hardware/gic.h>
33 35
34static void __iomem *gic_dist_base;
35static void __iomem *gic_cpu_base;
36static DEFINE_SPINLOCK(irq_controller_lock); 36static DEFINE_SPINLOCK(irq_controller_lock);
37 37
38struct gic_chip_data {
39 unsigned int irq_offset;
40 void __iomem *dist_base;
41 void __iomem *cpu_base;
42};
43
44#ifndef MAX_GIC_NR
45#define MAX_GIC_NR 1
46#endif
47
48static struct gic_chip_data gic_data[MAX_GIC_NR];
49
50static inline void __iomem *gic_dist_base(unsigned int irq)
51{
52 struct gic_chip_data *gic_data = get_irq_chip_data(irq);
53 return gic_data->dist_base;
54}
55
56static inline void __iomem *gic_cpu_base(unsigned int irq)
57{
58 struct gic_chip_data *gic_data = get_irq_chip_data(irq);
59 return gic_data->cpu_base;
60}
61
62static inline unsigned int gic_irq(unsigned int irq)
63{
64 struct gic_chip_data *gic_data = get_irq_chip_data(irq);
65 return irq - gic_data->irq_offset;
66}
67
38/* 68/*
39 * Routines to acknowledge, disable and enable interrupts 69 * Routines to acknowledge, disable and enable interrupts
40 * 70 *
@@ -55,8 +85,8 @@ static void gic_ack_irq(unsigned int irq)
55 u32 mask = 1 << (irq % 32); 85 u32 mask = 1 << (irq % 32);
56 86
57 spin_lock(&irq_controller_lock); 87 spin_lock(&irq_controller_lock);
58 writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); 88 writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
59 writel(irq, gic_cpu_base + GIC_CPU_EOI); 89 writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
60 spin_unlock(&irq_controller_lock); 90 spin_unlock(&irq_controller_lock);
61} 91}
62 92
@@ -65,7 +95,7 @@ static void gic_mask_irq(unsigned int irq)
65 u32 mask = 1 << (irq % 32); 95 u32 mask = 1 << (irq % 32);
66 96
67 spin_lock(&irq_controller_lock); 97 spin_lock(&irq_controller_lock);
68 writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); 98 writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
69 spin_unlock(&irq_controller_lock); 99 spin_unlock(&irq_controller_lock);
70} 100}
71 101
@@ -74,14 +104,14 @@ static void gic_unmask_irq(unsigned int irq)
74 u32 mask = 1 << (irq % 32); 104 u32 mask = 1 << (irq % 32);
75 105
76 spin_lock(&irq_controller_lock); 106 spin_lock(&irq_controller_lock);
77 writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4); 107 writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_SET + (gic_irq(irq) / 32) * 4);
78 spin_unlock(&irq_controller_lock); 108 spin_unlock(&irq_controller_lock);
79} 109}
80 110
81#ifdef CONFIG_SMP 111#ifdef CONFIG_SMP
82static void gic_set_cpu(unsigned int irq, cpumask_t mask_val) 112static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
83{ 113{
84 void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3); 114 void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
85 unsigned int shift = (irq % 4) * 8; 115 unsigned int shift = (irq % 4) * 8;
86 unsigned int cpu = first_cpu(mask_val); 116 unsigned int cpu = first_cpu(mask_val);
87 u32 val; 117 u32 val;
@@ -95,6 +125,37 @@ static void gic_set_cpu(unsigned int irq, cpumask_t mask_val)
95} 125}
96#endif 126#endif
97 127
128static void fastcall gic_handle_cascade_irq(unsigned int irq,
129 struct irq_desc *desc)
130{
131 struct gic_chip_data *chip_data = get_irq_data(irq);
132 struct irq_chip *chip = get_irq_chip(irq);
133 unsigned int cascade_irq;
134 unsigned long status;
135
136 /* primary controller ack'ing */
137 chip->ack(irq);
138
139 spin_lock(&irq_controller_lock);
140 status = readl(chip_data->cpu_base + GIC_CPU_INTACK);
141 spin_unlock(&irq_controller_lock);
142
143 cascade_irq = (status & 0x3ff);
144 if (cascade_irq > 1020)
145 goto out;
146 if (cascade_irq < 32 || cascade_irq >= NR_IRQS) {
147 do_bad_IRQ(cascade_irq, desc);
148 goto out;
149 }
150
151 cascade_irq += chip_data->irq_offset;
152 generic_handle_irq(cascade_irq);
153
154 out:
155 /* primary controller unmasking */
156 chip->unmask(irq);
157}
158
98static struct irq_chip gic_chip = { 159static struct irq_chip gic_chip = {
99 .name = "GIC", 160 .name = "GIC",
100 .ack = gic_ack_irq, 161 .ack = gic_ack_irq,
@@ -105,15 +166,29 @@ static struct irq_chip gic_chip = {
105#endif 166#endif
106}; 167};
107 168
108void __init gic_dist_init(void __iomem *base) 169void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
170{
171 if (gic_nr >= MAX_GIC_NR)
172 BUG();
173 if (set_irq_data(irq, &gic_data[gic_nr]) != 0)
174 BUG();
175 set_irq_chained_handler(irq, gic_handle_cascade_irq);
176}
177
178void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
179 unsigned int irq_start)
109{ 180{
110 unsigned int max_irq, i; 181 unsigned int max_irq, i;
111 u32 cpumask = 1 << smp_processor_id(); 182 u32 cpumask = 1 << smp_processor_id();
112 183
184 if (gic_nr >= MAX_GIC_NR)
185 BUG();
186
113 cpumask |= cpumask << 8; 187 cpumask |= cpumask << 8;
114 cpumask |= cpumask << 16; 188 cpumask |= cpumask << 16;
115 189
116 gic_dist_base = base; 190 gic_data[gic_nr].dist_base = base;
191 gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
117 192
118 writel(0, base + GIC_DIST_CTRL); 193 writel(0, base + GIC_DIST_CTRL);
119 194
@@ -158,8 +233,9 @@ void __init gic_dist_init(void __iomem *base)
158 /* 233 /*
159 * Setup the Linux IRQ subsystem. 234 * Setup the Linux IRQ subsystem.
160 */ 235 */
161 for (i = 29; i < max_irq; i++) { 236 for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) {
162 set_irq_chip(i, &gic_chip); 237 set_irq_chip(i, &gic_chip);
238 set_irq_chip_data(i, &gic_data[gic_nr]);
163 set_irq_handler(i, handle_level_irq); 239 set_irq_handler(i, handle_level_irq);
164 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 240 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
165 } 241 }
@@ -167,9 +243,13 @@ void __init gic_dist_init(void __iomem *base)
167 writel(1, base + GIC_DIST_CTRL); 243 writel(1, base + GIC_DIST_CTRL);
168} 244}
169 245
170void __cpuinit gic_cpu_init(void __iomem *base) 246void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
171{ 247{
172 gic_cpu_base = base; 248 if (gic_nr >= MAX_GIC_NR)
249 BUG();
250
251 gic_data[gic_nr].cpu_base = base;
252
173 writel(0xf0, base + GIC_CPU_PRIMASK); 253 writel(0xf0, base + GIC_CPU_PRIMASK);
174 writel(1, base + GIC_CPU_CTRL); 254 writel(1, base + GIC_CPU_CTRL);
175} 255}
@@ -179,6 +259,7 @@ void gic_raise_softirq(cpumask_t cpumask, unsigned int irq)
179{ 259{
180 unsigned long map = *cpus_addr(cpumask); 260 unsigned long map = *cpus_addr(cpumask);
181 261
182 writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT); 262 /* this always happens on GIC0 */
263 writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
183} 264}
184#endif 265#endif
diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
new file mode 100644
index 000000000000..c72ab82873d5
--- /dev/null
+++ b/arch/arm/configs/at91sam9263ek_defconfig
@@ -0,0 +1,1184 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.20-rc1
4# Mon Jan 8 16:06:54 2007
5#
6CONFIG_ARM=y
7# CONFIG_GENERIC_TIME is not set
8CONFIG_MMU=y
9CONFIG_GENERIC_HARDIRQS=y
10CONFIG_TRACE_IRQFLAGS_SUPPORT=y
11CONFIG_HARDIRQS_SW_RESEND=y
12CONFIG_GENERIC_IRQ_PROBE=y
13CONFIG_RWSEM_GENERIC_SPINLOCK=y
14# CONFIG_ARCH_HAS_ILOG2_U32 is not set
15# CONFIG_ARCH_HAS_ILOG2_U64 is not set
16CONFIG_GENERIC_HWEIGHT=y
17CONFIG_GENERIC_CALIBRATE_DELAY=y
18CONFIG_VECTORS_BASE=0xffff0000
19CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
20
21#
22# Code maturity level options
23#
24CONFIG_EXPERIMENTAL=y
25CONFIG_BROKEN_ON_SMP=y
26CONFIG_INIT_ENV_ARG_LIMIT=32
27
28#
29# General setup
30#
31CONFIG_LOCALVERSION=""
32# CONFIG_LOCALVERSION_AUTO is not set
33# CONFIG_SWAP is not set
34CONFIG_SYSVIPC=y
35# CONFIG_IPC_NS is not set
36# CONFIG_POSIX_MQUEUE is not set
37# CONFIG_BSD_PROCESS_ACCT is not set
38# CONFIG_TASKSTATS is not set
39# CONFIG_UTS_NS is not set
40# CONFIG_AUDIT is not set
41# CONFIG_IKCONFIG is not set
42CONFIG_SYSFS_DEPRECATED=y
43# CONFIG_RELAY is not set
44CONFIG_INITRAMFS_SOURCE=""
45CONFIG_CC_OPTIMIZE_FOR_SIZE=y
46CONFIG_SYSCTL=y
47# CONFIG_EMBEDDED is not set
48CONFIG_UID16=y
49CONFIG_SYSCTL_SYSCALL=y
50CONFIG_KALLSYMS=y
51# CONFIG_KALLSYMS_ALL is not set
52# CONFIG_KALLSYMS_EXTRA_PASS is not set
53CONFIG_HOTPLUG=y
54CONFIG_PRINTK=y
55CONFIG_BUG=y
56CONFIG_ELF_CORE=y
57CONFIG_BASE_FULL=y
58CONFIG_FUTEX=y
59CONFIG_EPOLL=y
60CONFIG_SHMEM=y
61CONFIG_SLAB=y
62CONFIG_VM_EVENT_COUNTERS=y
63CONFIG_RT_MUTEXES=y
64# CONFIG_TINY_SHMEM is not set
65CONFIG_BASE_SMALL=0
66# CONFIG_SLOB is not set
67
68#
69# Loadable module support
70#
71CONFIG_MODULES=y
72CONFIG_MODULE_UNLOAD=y
73# CONFIG_MODULE_FORCE_UNLOAD is not set
74# CONFIG_MODVERSIONS is not set
75# CONFIG_MODULE_SRCVERSION_ALL is not set
76CONFIG_KMOD=y
77
78#
79# Block layer
80#
81CONFIG_BLOCK=y
82# CONFIG_LBD is not set
83# CONFIG_BLK_DEV_IO_TRACE is not set
84# CONFIG_LSF is not set
85
86#
87# IO Schedulers
88#
89CONFIG_IOSCHED_NOOP=y
90CONFIG_IOSCHED_AS=y
91# CONFIG_IOSCHED_DEADLINE is not set
92# CONFIG_IOSCHED_CFQ is not set
93CONFIG_DEFAULT_AS=y
94# CONFIG_DEFAULT_DEADLINE is not set
95# CONFIG_DEFAULT_CFQ is not set
96# CONFIG_DEFAULT_NOOP is not set
97CONFIG_DEFAULT_IOSCHED="anticipatory"
98
99#
100# System Type
101#
102# CONFIG_ARCH_AAEC2000 is not set
103# CONFIG_ARCH_INTEGRATOR is not set
104# CONFIG_ARCH_REALVIEW is not set
105# CONFIG_ARCH_VERSATILE is not set
106CONFIG_ARCH_AT91=y
107# CONFIG_ARCH_CLPS7500 is not set
108# CONFIG_ARCH_CLPS711X is not set
109# CONFIG_ARCH_CO285 is not set
110# CONFIG_ARCH_EBSA110 is not set
111# CONFIG_ARCH_EP93XX is not set
112# CONFIG_ARCH_FOOTBRIDGE is not set
113# CONFIG_ARCH_NETX is not set
114# CONFIG_ARCH_H720X is not set
115# CONFIG_ARCH_IMX is not set
116# CONFIG_ARCH_IOP32X is not set
117# CONFIG_ARCH_IOP33X is not set
118# CONFIG_ARCH_IOP13XX is not set
119# CONFIG_ARCH_IXP4XX is not set
120# CONFIG_ARCH_IXP2000 is not set
121# CONFIG_ARCH_IXP23XX is not set
122# CONFIG_ARCH_L7200 is not set
123# CONFIG_ARCH_PNX4008 is not set
124# CONFIG_ARCH_PXA is not set
125# CONFIG_ARCH_RPC is not set
126# CONFIG_ARCH_SA1100 is not set
127# CONFIG_ARCH_S3C2410 is not set
128# CONFIG_ARCH_SHARK is not set
129# CONFIG_ARCH_LH7A40X is not set
130# CONFIG_ARCH_OMAP is not set
131
132#
133# Atmel AT91 System-on-Chip
134#
135# CONFIG_ARCH_AT91RM9200 is not set
136# CONFIG_ARCH_AT91SAM9260 is not set
137# CONFIG_ARCH_AT91SAM9261 is not set
138CONFIG_ARCH_AT91SAM9263=y
139
140#
141# AT91SAM9263 Board Type
142#
143CONFIG_MACH_AT91SAM9263EK=y
144
145#
146# AT91 Board Options
147#
148CONFIG_MTD_AT91_DATAFLASH_CARD=y
149# CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set
150
151#
152# AT91 Feature Selections
153#
154# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
155
156#
157# Processor Type
158#
159CONFIG_CPU_32=y
160CONFIG_CPU_ARM926T=y
161CONFIG_CPU_32v5=y
162CONFIG_CPU_ABRT_EV5TJ=y
163CONFIG_CPU_CACHE_VIVT=y
164CONFIG_CPU_COPY_V4WB=y
165CONFIG_CPU_TLB_V4WBI=y
166CONFIG_CPU_CP15=y
167CONFIG_CPU_CP15_MMU=y
168
169#
170# Processor Features
171#
172# CONFIG_ARM_THUMB is not set
173# CONFIG_CPU_ICACHE_DISABLE is not set
174# CONFIG_CPU_DCACHE_DISABLE is not set
175# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
176# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
177
178#
179# Bus support
180#
181
182#
183# PCCARD (PCMCIA/CardBus) support
184#
185# CONFIG_PCCARD is not set
186
187#
188# Kernel Features
189#
190# CONFIG_PREEMPT is not set
191# CONFIG_NO_IDLE_HZ is not set
192CONFIG_HZ=100
193# CONFIG_AEABI is not set
194# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
195CONFIG_SELECT_MEMORY_MODEL=y
196CONFIG_FLATMEM_MANUAL=y
197# CONFIG_DISCONTIGMEM_MANUAL is not set
198# CONFIG_SPARSEMEM_MANUAL is not set
199CONFIG_FLATMEM=y
200CONFIG_FLAT_NODE_MEM_MAP=y
201# CONFIG_SPARSEMEM_STATIC is not set
202CONFIG_SPLIT_PTLOCK_CPUS=4096
203# CONFIG_RESOURCES_64BIT is not set
204# CONFIG_LEDS is not set
205CONFIG_ALIGNMENT_TRAP=y
206
207#
208# Boot options
209#
210CONFIG_ZBOOT_ROM_TEXT=0x0
211CONFIG_ZBOOT_ROM_BSS=0x0
212CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
213# CONFIG_XIP_KERNEL is not set
214
215#
216# Floating point emulation
217#
218
219#
220# At least one emulation must be selected
221#
222CONFIG_FPE_NWFPE=y
223# CONFIG_FPE_NWFPE_XP is not set
224# CONFIG_FPE_FASTFPE is not set
225# CONFIG_VFP is not set
226
227#
228# Userspace binary formats
229#
230CONFIG_BINFMT_ELF=y
231# CONFIG_BINFMT_AOUT is not set
232# CONFIG_BINFMT_MISC is not set
233# CONFIG_ARTHUR is not set
234
235#
236# Power management options
237#
238# CONFIG_PM is not set
239# CONFIG_APM is not set
240
241#
242# Networking
243#
244CONFIG_NET=y
245
246#
247# Networking options
248#
249# CONFIG_NETDEBUG is not set
250CONFIG_PACKET=y
251# CONFIG_PACKET_MMAP is not set
252CONFIG_UNIX=y
253# CONFIG_NET_KEY is not set
254CONFIG_INET=y
255# CONFIG_IP_MULTICAST is not set
256# CONFIG_IP_ADVANCED_ROUTER is not set
257CONFIG_IP_FIB_HASH=y
258CONFIG_IP_PNP=y
259# CONFIG_IP_PNP_DHCP is not set
260CONFIG_IP_PNP_BOOTP=y
261CONFIG_IP_PNP_RARP=y
262# CONFIG_NET_IPIP is not set
263# CONFIG_NET_IPGRE is not set
264# CONFIG_ARPD is not set
265# CONFIG_SYN_COOKIES is not set
266# CONFIG_INET_AH is not set
267# CONFIG_INET_ESP is not set
268# CONFIG_INET_IPCOMP is not set
269# CONFIG_INET_XFRM_TUNNEL is not set
270# CONFIG_INET_TUNNEL is not set
271# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
272# CONFIG_INET_XFRM_MODE_TUNNEL is not set
273# CONFIG_INET_XFRM_MODE_BEET is not set
274# CONFIG_INET_DIAG is not set
275# CONFIG_TCP_CONG_ADVANCED is not set
276CONFIG_TCP_CONG_CUBIC=y
277CONFIG_DEFAULT_TCP_CONG="cubic"
278# CONFIG_TCP_MD5SIG is not set
279# CONFIG_IPV6 is not set
280# CONFIG_INET6_XFRM_TUNNEL is not set
281# CONFIG_INET6_TUNNEL is not set
282# CONFIG_NETWORK_SECMARK is not set
283# CONFIG_NETFILTER is not set
284
285#
286# DCCP Configuration (EXPERIMENTAL)
287#
288# CONFIG_IP_DCCP is not set
289
290#
291# SCTP Configuration (EXPERIMENTAL)
292#
293# CONFIG_IP_SCTP is not set
294
295#
296# TIPC Configuration (EXPERIMENTAL)
297#
298# CONFIG_TIPC is not set
299# CONFIG_ATM is not set
300# CONFIG_BRIDGE is not set
301# CONFIG_VLAN_8021Q is not set
302# CONFIG_DECNET is not set
303# CONFIG_LLC2 is not set
304# CONFIG_IPX is not set
305# CONFIG_ATALK is not set
306# CONFIG_X25 is not set
307# CONFIG_LAPB is not set
308# CONFIG_ECONET is not set
309# CONFIG_WAN_ROUTER is not set
310
311#
312# QoS and/or fair queueing
313#
314# CONFIG_NET_SCHED is not set
315
316#
317# Network testing
318#
319# CONFIG_NET_PKTGEN is not set
320# CONFIG_HAMRADIO is not set
321# CONFIG_IRDA is not set
322# CONFIG_BT is not set
323# CONFIG_IEEE80211 is not set
324
325#
326# Device Drivers
327#
328
329#
330# Generic Driver Options
331#
332CONFIG_STANDALONE=y
333CONFIG_PREVENT_FIRMWARE_BUILD=y
334# CONFIG_FW_LOADER is not set
335# CONFIG_DEBUG_DRIVER is not set
336# CONFIG_SYS_HYPERVISOR is not set
337
338#
339# Connector - unified userspace <-> kernelspace linker
340#
341# CONFIG_CONNECTOR is not set
342
343#
344# Memory Technology Devices (MTD)
345#
346CONFIG_MTD=y
347# CONFIG_MTD_DEBUG is not set
348# CONFIG_MTD_CONCAT is not set
349CONFIG_MTD_PARTITIONS=y
350# CONFIG_MTD_REDBOOT_PARTS is not set
351CONFIG_MTD_CMDLINE_PARTS=y
352# CONFIG_MTD_AFS_PARTS is not set
353
354#
355# User Modules And Translation Layers
356#
357CONFIG_MTD_CHAR=y
358CONFIG_MTD_BLKDEVS=y
359CONFIG_MTD_BLOCK=y
360# CONFIG_FTL is not set
361# CONFIG_NFTL is not set
362# CONFIG_INFTL is not set
363# CONFIG_RFD_FTL is not set
364# CONFIG_SSFDC is not set
365
366#
367# RAM/ROM/Flash chip drivers
368#
369# CONFIG_MTD_CFI is not set
370# CONFIG_MTD_JEDECPROBE is not set
371CONFIG_MTD_MAP_BANK_WIDTH_1=y
372CONFIG_MTD_MAP_BANK_WIDTH_2=y
373CONFIG_MTD_MAP_BANK_WIDTH_4=y
374# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
375# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
376# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
377CONFIG_MTD_CFI_I1=y
378CONFIG_MTD_CFI_I2=y
379# CONFIG_MTD_CFI_I4 is not set
380# CONFIG_MTD_CFI_I8 is not set
381# CONFIG_MTD_RAM is not set
382# CONFIG_MTD_ROM is not set
383# CONFIG_MTD_ABSENT is not set
384# CONFIG_MTD_OBSOLETE_CHIPS is not set
385
386#
387# Mapping drivers for chip access
388#
389# CONFIG_MTD_COMPLEX_MAPPINGS is not set
390# CONFIG_MTD_PLATRAM is not set
391
392#
393# Self-contained MTD device drivers
394#
395CONFIG_MTD_DATAFLASH=y
396# CONFIG_MTD_M25P80 is not set
397# CONFIG_MTD_SLRAM is not set
398# CONFIG_MTD_PHRAM is not set
399# CONFIG_MTD_MTDRAM is not set
400# CONFIG_MTD_BLOCK2MTD is not set
401
402#
403# Disk-On-Chip Device Drivers
404#
405# CONFIG_MTD_DOC2000 is not set
406# CONFIG_MTD_DOC2001 is not set
407# CONFIG_MTD_DOC2001PLUS is not set
408
409#
410# NAND Flash Device Drivers
411#
412CONFIG_MTD_NAND=y
413# CONFIG_MTD_NAND_VERIFY_WRITE is not set
414# CONFIG_MTD_NAND_ECC_SMC is not set
415CONFIG_MTD_NAND_IDS=y
416# CONFIG_MTD_NAND_DISKONCHIP is not set
417CONFIG_MTD_NAND_AT91=y
418# CONFIG_MTD_NAND_NANDSIM is not set
419
420#
421# OneNAND Flash Device Drivers
422#
423# CONFIG_MTD_ONENAND is not set
424
425#
426# Parallel port support
427#
428# CONFIG_PARPORT is not set
429
430#
431# Plug and Play support
432#
433
434#
435# Block devices
436#
437# CONFIG_BLK_DEV_COW_COMMON is not set
438CONFIG_BLK_DEV_LOOP=y
439# CONFIG_BLK_DEV_CRYPTOLOOP is not set
440# CONFIG_BLK_DEV_NBD is not set
441# CONFIG_BLK_DEV_UB is not set
442CONFIG_BLK_DEV_RAM=y
443CONFIG_BLK_DEV_RAM_COUNT=16
444CONFIG_BLK_DEV_RAM_SIZE=8192
445CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
446CONFIG_BLK_DEV_INITRD=y
447# CONFIG_CDROM_PKTCDVD is not set
448# CONFIG_ATA_OVER_ETH is not set
449
450#
451# SCSI device support
452#
453# CONFIG_RAID_ATTRS is not set
454CONFIG_SCSI=y
455# CONFIG_SCSI_TGT is not set
456# CONFIG_SCSI_NETLINK is not set
457CONFIG_SCSI_PROC_FS=y
458
459#
460# SCSI support type (disk, tape, CD-ROM)
461#
462CONFIG_BLK_DEV_SD=y
463# CONFIG_CHR_DEV_ST is not set
464# CONFIG_CHR_DEV_OSST is not set
465# CONFIG_BLK_DEV_SR is not set
466# CONFIG_CHR_DEV_SG is not set
467# CONFIG_CHR_DEV_SCH is not set
468
469#
470# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
471#
472CONFIG_SCSI_MULTI_LUN=y
473# CONFIG_SCSI_CONSTANTS is not set
474# CONFIG_SCSI_LOGGING is not set
475# CONFIG_SCSI_SCAN_ASYNC is not set
476
477#
478# SCSI Transports
479#
480# CONFIG_SCSI_SPI_ATTRS is not set
481# CONFIG_SCSI_FC_ATTRS is not set
482# CONFIG_SCSI_ISCSI_ATTRS is not set
483# CONFIG_SCSI_SAS_ATTRS is not set
484# CONFIG_SCSI_SAS_LIBSAS is not set
485
486#
487# SCSI low-level drivers
488#
489# CONFIG_ISCSI_TCP is not set
490# CONFIG_SCSI_DEBUG is not set
491
492#
493# Serial ATA (prod) and Parallel ATA (experimental) drivers
494#
495# CONFIG_ATA is not set
496
497#
498# Multi-device support (RAID and LVM)
499#
500# CONFIG_MD is not set
501
502#
503# Fusion MPT device support
504#
505# CONFIG_FUSION is not set
506
507#
508# IEEE 1394 (FireWire) support
509#
510
511#
512# I2O device support
513#
514
515#
516# Network device support
517#
518CONFIG_NETDEVICES=y
519# CONFIG_DUMMY is not set
520# CONFIG_BONDING is not set
521# CONFIG_EQUALIZER is not set
522# CONFIG_TUN is not set
523
524#
525# PHY device support
526#
527# CONFIG_PHYLIB is not set
528
529#
530# Ethernet (10 or 100Mbit)
531#
532CONFIG_NET_ETHERNET=y
533CONFIG_MII=y
534# CONFIG_SMC91X is not set
535# CONFIG_DM9000 is not set
536
537#
538# Ethernet (1000 Mbit)
539#
540
541#
542# Ethernet (10000 Mbit)
543#
544
545#
546# Token Ring devices
547#
548
549#
550# Wireless LAN (non-hamradio)
551#
552# CONFIG_NET_RADIO is not set
553
554#
555# Wan interfaces
556#
557# CONFIG_WAN is not set
558# CONFIG_PPP is not set
559# CONFIG_SLIP is not set
560# CONFIG_SHAPER is not set
561# CONFIG_NETCONSOLE is not set
562# CONFIG_NETPOLL is not set
563# CONFIG_NET_POLL_CONTROLLER is not set
564
565#
566# ISDN subsystem
567#
568# CONFIG_ISDN is not set
569
570#
571# Input device support
572#
573CONFIG_INPUT=y
574# CONFIG_INPUT_FF_MEMLESS is not set
575
576#
577# Userland interfaces
578#
579CONFIG_INPUT_MOUSEDEV=y
580# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
581CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
582CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
583# CONFIG_INPUT_JOYDEV is not set
584CONFIG_INPUT_TSDEV=y
585CONFIG_INPUT_TSDEV_SCREEN_X=240
586CONFIG_INPUT_TSDEV_SCREEN_Y=320
587CONFIG_INPUT_EVDEV=y
588# CONFIG_INPUT_EVBUG is not set
589
590#
591# Input Device Drivers
592#
593# CONFIG_INPUT_KEYBOARD is not set
594# CONFIG_INPUT_MOUSE is not set
595# CONFIG_INPUT_JOYSTICK is not set
596CONFIG_INPUT_TOUCHSCREEN=y
597CONFIG_TOUCHSCREEN_ADS7846=y
598# CONFIG_TOUCHSCREEN_GUNZE is not set
599# CONFIG_TOUCHSCREEN_ELO is not set
600# CONFIG_TOUCHSCREEN_MTOUCH is not set
601# CONFIG_TOUCHSCREEN_MK712 is not set
602# CONFIG_TOUCHSCREEN_PENMOUNT is not set
603# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
604# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
605# CONFIG_TOUCHSCREEN_UCB1400 is not set
606# CONFIG_INPUT_MISC is not set
607
608#
609# Hardware I/O ports
610#
611# CONFIG_SERIO is not set
612# CONFIG_GAMEPORT is not set
613
614#
615# Character devices
616#
617CONFIG_VT=y
618CONFIG_VT_CONSOLE=y
619CONFIG_HW_CONSOLE=y
620# CONFIG_VT_HW_CONSOLE_BINDING is not set
621# CONFIG_SERIAL_NONSTANDARD is not set
622
623#
624# Serial drivers
625#
626# CONFIG_SERIAL_8250 is not set
627
628#
629# Non-8250 serial port support
630#
631CONFIG_SERIAL_ATMEL=y
632CONFIG_SERIAL_ATMEL_CONSOLE=y
633# CONFIG_SERIAL_ATMEL_TTYAT is not set
634CONFIG_SERIAL_CORE=y
635CONFIG_SERIAL_CORE_CONSOLE=y
636CONFIG_UNIX98_PTYS=y
637CONFIG_LEGACY_PTYS=y
638CONFIG_LEGACY_PTY_COUNT=256
639
640#
641# IPMI
642#
643# CONFIG_IPMI_HANDLER is not set
644
645#
646# Watchdog Cards
647#
648CONFIG_WATCHDOG=y
649CONFIG_WATCHDOG_NOWAYOUT=y
650
651#
652# Watchdog Device Drivers
653#
654# CONFIG_SOFT_WATCHDOG is not set
655
656#
657# USB-based Watchdog Cards
658#
659# CONFIG_USBPCWATCHDOG is not set
660CONFIG_HW_RANDOM=y
661# CONFIG_NVRAM is not set
662# CONFIG_DTLK is not set
663# CONFIG_R3964 is not set
664# CONFIG_RAW_DRIVER is not set
665
666#
667# TPM devices
668#
669# CONFIG_TCG_TPM is not set
670
671#
672# I2C support
673#
674CONFIG_I2C=y
675CONFIG_I2C_CHARDEV=y
676
677#
678# I2C Algorithms
679#
680# CONFIG_I2C_ALGOBIT is not set
681# CONFIG_I2C_ALGOPCF is not set
682# CONFIG_I2C_ALGOPCA is not set
683
684#
685# I2C Hardware Bus support
686#
687CONFIG_I2C_AT91=y
688# CONFIG_I2C_OCORES is not set
689# CONFIG_I2C_PARPORT_LIGHT is not set
690# CONFIG_I2C_STUB is not set
691# CONFIG_I2C_PCA is not set
692# CONFIG_I2C_PCA_ISA is not set
693
694#
695# Miscellaneous I2C Chip support
696#
697# CONFIG_SENSORS_DS1337 is not set
698# CONFIG_SENSORS_DS1374 is not set
699# CONFIG_SENSORS_EEPROM is not set
700# CONFIG_SENSORS_PCF8574 is not set
701# CONFIG_SENSORS_PCA9539 is not set
702# CONFIG_SENSORS_PCF8591 is not set
703# CONFIG_SENSORS_MAX6875 is not set
704# CONFIG_I2C_DEBUG_CORE is not set
705# CONFIG_I2C_DEBUG_ALGO is not set
706# CONFIG_I2C_DEBUG_BUS is not set
707# CONFIG_I2C_DEBUG_CHIP is not set
708
709#
710# SPI support
711#
712CONFIG_SPI=y
713# CONFIG_SPI_DEBUG is not set
714CONFIG_SPI_MASTER=y
715
716#
717# SPI Master Controller Drivers
718#
719CONFIG_SPI_ATMEL=y
720# CONFIG_SPI_BITBANG is not set
721
722#
723# SPI Protocol Masters
724#
725
726#
727# Dallas's 1-wire bus
728#
729# CONFIG_W1 is not set
730
731#
732# Hardware Monitoring support
733#
734# CONFIG_HWMON is not set
735# CONFIG_HWMON_VID is not set
736
737#
738# Misc devices
739#
740# CONFIG_TIFM_CORE is not set
741
742#
743# LED devices
744#
745# CONFIG_NEW_LEDS is not set
746
747#
748# LED drivers
749#
750
751#
752# LED Triggers
753#
754
755#
756# Multimedia devices
757#
758# CONFIG_VIDEO_DEV is not set
759
760#
761# Digital Video Broadcasting Devices
762#
763# CONFIG_DVB is not set
764# CONFIG_USB_DABUSB is not set
765
766#
767# Graphics support
768#
769# CONFIG_FIRMWARE_EDID is not set
770CONFIG_FB=y
771# CONFIG_FB_CFB_FILLRECT is not set
772# CONFIG_FB_CFB_COPYAREA is not set
773# CONFIG_FB_CFB_IMAGEBLIT is not set
774# CONFIG_FB_MACMODES is not set
775# CONFIG_FB_BACKLIGHT is not set
776# CONFIG_FB_MODE_HELPERS is not set
777# CONFIG_FB_TILEBLITTING is not set
778# CONFIG_FB_S1D13XXX is not set
779# CONFIG_FB_VIRTUAL is not set
780
781#
782# Console display driver support
783#
784# CONFIG_VGA_CONSOLE is not set
785CONFIG_DUMMY_CONSOLE=y
786# CONFIG_FRAMEBUFFER_CONSOLE is not set
787
788#
789# Logo configuration
790#
791# CONFIG_LOGO is not set
792# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
793
794#
795# Sound
796#
797# CONFIG_SOUND is not set
798
799#
800# HID Devices
801#
802CONFIG_HID=y
803
804#
805# USB support
806#
807CONFIG_USB_ARCH_HAS_HCD=y
808CONFIG_USB_ARCH_HAS_OHCI=y
809# CONFIG_USB_ARCH_HAS_EHCI is not set
810CONFIG_USB=y
811# CONFIG_USB_DEBUG is not set
812
813#
814# Miscellaneous USB options
815#
816CONFIG_USB_DEVICEFS=y
817# CONFIG_USB_BANDWIDTH is not set
818# CONFIG_USB_DYNAMIC_MINORS is not set
819# CONFIG_USB_MULTITHREAD_PROBE is not set
820# CONFIG_USB_OTG is not set
821
822#
823# USB Host Controller Drivers
824#
825# CONFIG_USB_ISP116X_HCD is not set
826CONFIG_USB_OHCI_HCD=y
827# CONFIG_USB_OHCI_BIG_ENDIAN is not set
828CONFIG_USB_OHCI_LITTLE_ENDIAN=y
829# CONFIG_USB_SL811_HCD is not set
830
831#
832# USB Device Class drivers
833#
834# CONFIG_USB_ACM is not set
835# CONFIG_USB_PRINTER is not set
836
837#
838# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
839#
840
841#
842# may also be needed; see USB_STORAGE Help for more information
843#
844CONFIG_USB_STORAGE=y
845# CONFIG_USB_STORAGE_DEBUG is not set
846# CONFIG_USB_STORAGE_DATAFAB is not set
847# CONFIG_USB_STORAGE_FREECOM is not set
848# CONFIG_USB_STORAGE_DPCM is not set
849# CONFIG_USB_STORAGE_USBAT is not set
850# CONFIG_USB_STORAGE_SDDR09 is not set
851# CONFIG_USB_STORAGE_SDDR55 is not set
852# CONFIG_USB_STORAGE_JUMPSHOT is not set
853# CONFIG_USB_STORAGE_ALAUDA is not set
854# CONFIG_USB_STORAGE_ONETOUCH is not set
855# CONFIG_USB_STORAGE_KARMA is not set
856# CONFIG_USB_LIBUSUAL is not set
857
858#
859# USB Input Devices
860#
861# CONFIG_USB_HID is not set
862
863#
864# USB HID Boot Protocol drivers
865#
866# CONFIG_USB_KBD is not set
867# CONFIG_USB_MOUSE is not set
868# CONFIG_USB_AIPTEK is not set
869# CONFIG_USB_WACOM is not set
870# CONFIG_USB_ACECAD is not set
871# CONFIG_USB_KBTAB is not set
872# CONFIG_USB_POWERMATE is not set
873# CONFIG_USB_TOUCHSCREEN is not set
874# CONFIG_USB_YEALINK is not set
875# CONFIG_USB_XPAD is not set
876# CONFIG_USB_ATI_REMOTE is not set
877# CONFIG_USB_ATI_REMOTE2 is not set
878# CONFIG_USB_KEYSPAN_REMOTE is not set
879# CONFIG_USB_APPLETOUCH is not set
880
881#
882# USB Imaging devices
883#
884# CONFIG_USB_MDC800 is not set
885# CONFIG_USB_MICROTEK is not set
886
887#
888# USB Network Adapters
889#
890# CONFIG_USB_CATC is not set
891# CONFIG_USB_KAWETH is not set
892# CONFIG_USB_PEGASUS is not set
893# CONFIG_USB_RTL8150 is not set
894# CONFIG_USB_USBNET_MII is not set
895# CONFIG_USB_USBNET is not set
896CONFIG_USB_MON=y
897
898#
899# USB port drivers
900#
901
902#
903# USB Serial Converter support
904#
905# CONFIG_USB_SERIAL is not set
906
907#
908# USB Miscellaneous drivers
909#
910# CONFIG_USB_EMI62 is not set
911# CONFIG_USB_EMI26 is not set
912# CONFIG_USB_ADUTUX is not set
913# CONFIG_USB_AUERSWALD is not set
914# CONFIG_USB_RIO500 is not set
915# CONFIG_USB_LEGOTOWER is not set
916# CONFIG_USB_LCD is not set
917# CONFIG_USB_LED is not set
918# CONFIG_USB_CYPRESS_CY7C63 is not set
919# CONFIG_USB_CYTHERM is not set
920# CONFIG_USB_PHIDGET is not set
921# CONFIG_USB_IDMOUSE is not set
922# CONFIG_USB_FTDI_ELAN is not set
923# CONFIG_USB_APPLEDISPLAY is not set
924# CONFIG_USB_LD is not set
925# CONFIG_USB_TRANCEVIBRATOR is not set
926# CONFIG_USB_TEST is not set
927
928#
929# USB DSL modem support
930#
931
932#
933# USB Gadget Support
934#
935CONFIG_USB_GADGET=y
936# CONFIG_USB_GADGET_DEBUG_FILES is not set
937CONFIG_USB_GADGET_SELECTED=y
938# CONFIG_USB_GADGET_NET2280 is not set
939# CONFIG_USB_GADGET_PXA2XX is not set
940# CONFIG_USB_GADGET_GOKU is not set
941# CONFIG_USB_GADGET_LH7A40X is not set
942# CONFIG_USB_GADGET_OMAP is not set
943CONFIG_USB_GADGET_AT91=y
944CONFIG_USB_AT91=y
945# CONFIG_USB_GADGET_DUMMY_HCD is not set
946# CONFIG_USB_GADGET_DUALSPEED is not set
947CONFIG_USB_ZERO=m
948# CONFIG_USB_ETH is not set
949CONFIG_USB_GADGETFS=m
950CONFIG_USB_FILE_STORAGE=m
951# CONFIG_USB_FILE_STORAGE_TEST is not set
952CONFIG_USB_G_SERIAL=m
953# CONFIG_USB_MIDI_GADGET is not set
954
955#
956# MMC/SD Card support
957#
958CONFIG_MMC=y
959# CONFIG_MMC_DEBUG is not set
960CONFIG_MMC_BLOCK=y
961CONFIG_MMC_AT91=m
962# CONFIG_MMC_TIFM_SD is not set
963
964#
965# Real Time Clock
966#
967CONFIG_RTC_LIB=y
968# CONFIG_RTC_CLASS is not set
969
970#
971# File systems
972#
973CONFIG_EXT2_FS=y
974# CONFIG_EXT2_FS_XATTR is not set
975# CONFIG_EXT2_FS_XIP is not set
976# CONFIG_EXT3_FS is not set
977# CONFIG_EXT4DEV_FS is not set
978# CONFIG_REISERFS_FS is not set
979# CONFIG_JFS_FS is not set
980# CONFIG_FS_POSIX_ACL is not set
981# CONFIG_XFS_FS is not set
982# CONFIG_GFS2_FS is not set
983# CONFIG_OCFS2_FS is not set
984# CONFIG_MINIX_FS is not set
985# CONFIG_ROMFS_FS is not set
986CONFIG_INOTIFY=y
987CONFIG_INOTIFY_USER=y
988# CONFIG_QUOTA is not set
989CONFIG_DNOTIFY=y
990# CONFIG_AUTOFS_FS is not set
991# CONFIG_AUTOFS4_FS is not set
992# CONFIG_FUSE_FS is not set
993
994#
995# CD-ROM/DVD Filesystems
996#
997# CONFIG_ISO9660_FS is not set
998# CONFIG_UDF_FS is not set
999
1000#
1001# DOS/FAT/NT Filesystems
1002#
1003CONFIG_FAT_FS=y
1004# CONFIG_MSDOS_FS is not set
1005CONFIG_VFAT_FS=y
1006CONFIG_FAT_DEFAULT_CODEPAGE=437
1007CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
1008# CONFIG_NTFS_FS is not set
1009
1010#
1011# Pseudo filesystems
1012#
1013CONFIG_PROC_FS=y
1014CONFIG_PROC_SYSCTL=y
1015CONFIG_SYSFS=y
1016CONFIG_TMPFS=y
1017# CONFIG_TMPFS_POSIX_ACL is not set
1018# CONFIG_HUGETLB_PAGE is not set
1019CONFIG_RAMFS=y
1020# CONFIG_CONFIGFS_FS is not set
1021
1022#
1023# Miscellaneous filesystems
1024#
1025# CONFIG_ADFS_FS is not set
1026# CONFIG_AFFS_FS is not set
1027# CONFIG_HFS_FS is not set
1028# CONFIG_HFSPLUS_FS is not set
1029# CONFIG_BEFS_FS is not set
1030# CONFIG_BFS_FS is not set
1031# CONFIG_EFS_FS is not set
1032CONFIG_JFFS2_FS=y
1033CONFIG_JFFS2_FS_DEBUG=0
1034CONFIG_JFFS2_FS_WRITEBUFFER=y
1035# CONFIG_JFFS2_SUMMARY is not set
1036# CONFIG_JFFS2_FS_XATTR is not set
1037# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
1038CONFIG_JFFS2_ZLIB=y
1039CONFIG_JFFS2_RTIME=y
1040# CONFIG_JFFS2_RUBIN is not set
1041CONFIG_CRAMFS=y
1042# CONFIG_VXFS_FS is not set
1043# CONFIG_HPFS_FS is not set
1044# CONFIG_QNX4FS_FS is not set
1045# CONFIG_SYSV_FS is not set
1046# CONFIG_UFS_FS is not set
1047
1048#
1049# Network File Systems
1050#
1051CONFIG_NFS_FS=y
1052# CONFIG_NFS_V3 is not set
1053# CONFIG_NFS_V4 is not set
1054# CONFIG_NFS_DIRECTIO is not set
1055# CONFIG_NFSD is not set
1056CONFIG_ROOT_NFS=y
1057CONFIG_LOCKD=y
1058CONFIG_NFS_COMMON=y
1059CONFIG_SUNRPC=y
1060# CONFIG_RPCSEC_GSS_KRB5 is not set
1061# CONFIG_RPCSEC_GSS_SPKM3 is not set
1062# CONFIG_SMB_FS is not set
1063# CONFIG_CIFS is not set
1064# CONFIG_NCP_FS is not set
1065# CONFIG_CODA_FS is not set
1066# CONFIG_AFS_FS is not set
1067# CONFIG_9P_FS is not set
1068
1069#
1070# Partition Types
1071#
1072# CONFIG_PARTITION_ADVANCED is not set
1073CONFIG_MSDOS_PARTITION=y
1074
1075#
1076# Native Language Support
1077#
1078CONFIG_NLS=y
1079CONFIG_NLS_DEFAULT="iso8859-1"
1080CONFIG_NLS_CODEPAGE_437=y
1081# CONFIG_NLS_CODEPAGE_737 is not set
1082# CONFIG_NLS_CODEPAGE_775 is not set
1083CONFIG_NLS_CODEPAGE_850=y
1084# CONFIG_NLS_CODEPAGE_852 is not set
1085# CONFIG_NLS_CODEPAGE_855 is not set
1086# CONFIG_NLS_CODEPAGE_857 is not set
1087# CONFIG_NLS_CODEPAGE_860 is not set
1088# CONFIG_NLS_CODEPAGE_861 is not set
1089# CONFIG_NLS_CODEPAGE_862 is not set
1090# CONFIG_NLS_CODEPAGE_863 is not set
1091# CONFIG_NLS_CODEPAGE_864 is not set
1092# CONFIG_NLS_CODEPAGE_865 is not set
1093# CONFIG_NLS_CODEPAGE_866 is not set
1094# CONFIG_NLS_CODEPAGE_869 is not set
1095# CONFIG_NLS_CODEPAGE_936 is not set
1096# CONFIG_NLS_CODEPAGE_950 is not set
1097# CONFIG_NLS_CODEPAGE_932 is not set
1098# CONFIG_NLS_CODEPAGE_949 is not set
1099# CONFIG_NLS_CODEPAGE_874 is not set
1100# CONFIG_NLS_ISO8859_8 is not set
1101# CONFIG_NLS_CODEPAGE_1250 is not set
1102# CONFIG_NLS_CODEPAGE_1251 is not set
1103# CONFIG_NLS_ASCII is not set
1104CONFIG_NLS_ISO8859_1=y
1105# CONFIG_NLS_ISO8859_2 is not set
1106# CONFIG_NLS_ISO8859_3 is not set
1107# CONFIG_NLS_ISO8859_4 is not set
1108# CONFIG_NLS_ISO8859_5 is not set
1109# CONFIG_NLS_ISO8859_6 is not set
1110# CONFIG_NLS_ISO8859_7 is not set
1111# CONFIG_NLS_ISO8859_9 is not set
1112# CONFIG_NLS_ISO8859_13 is not set
1113# CONFIG_NLS_ISO8859_14 is not set
1114# CONFIG_NLS_ISO8859_15 is not set
1115# CONFIG_NLS_KOI8_R is not set
1116# CONFIG_NLS_KOI8_U is not set
1117# CONFIG_NLS_UTF8 is not set
1118
1119#
1120# Distributed Lock Manager
1121#
1122# CONFIG_DLM is not set
1123
1124#
1125# Profiling support
1126#
1127# CONFIG_PROFILING is not set
1128
1129#
1130# Kernel hacking
1131#
1132# CONFIG_PRINTK_TIME is not set
1133CONFIG_ENABLE_MUST_CHECK=y
1134# CONFIG_MAGIC_SYSRQ is not set
1135# CONFIG_UNUSED_SYMBOLS is not set
1136# CONFIG_DEBUG_FS is not set
1137# CONFIG_HEADERS_CHECK is not set
1138CONFIG_DEBUG_KERNEL=y
1139CONFIG_LOG_BUF_SHIFT=14
1140CONFIG_DETECT_SOFTLOCKUP=y
1141# CONFIG_SCHEDSTATS is not set
1142# CONFIG_DEBUG_SLAB is not set
1143# CONFIG_DEBUG_RT_MUTEXES is not set
1144# CONFIG_RT_MUTEX_TESTER is not set
1145# CONFIG_DEBUG_SPINLOCK is not set
1146# CONFIG_DEBUG_MUTEXES is not set
1147# CONFIG_DEBUG_RWSEMS is not set
1148# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
1149# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
1150# CONFIG_DEBUG_KOBJECT is not set
1151CONFIG_DEBUG_BUGVERBOSE=y
1152# CONFIG_DEBUG_INFO is not set
1153# CONFIG_DEBUG_VM is not set
1154# CONFIG_DEBUG_LIST is not set
1155CONFIG_FRAME_POINTER=y
1156CONFIG_FORCED_INLINING=y
1157# CONFIG_RCU_TORTURE_TEST is not set
1158CONFIG_DEBUG_USER=y
1159# CONFIG_DEBUG_ERRORS is not set
1160CONFIG_DEBUG_LL=y
1161# CONFIG_DEBUG_ICEDCC is not set
1162
1163#
1164# Security options
1165#
1166# CONFIG_KEYS is not set
1167# CONFIG_SECURITY is not set
1168
1169#
1170# Cryptographic options
1171#
1172# CONFIG_CRYPTO is not set
1173
1174#
1175# Library routines
1176#
1177CONFIG_BITREVERSE=y
1178# CONFIG_CRC_CCITT is not set
1179# CONFIG_CRC16 is not set
1180CONFIG_CRC32=y
1181# CONFIG_LIBCRC32C is not set
1182CONFIG_ZLIB_INFLATE=y
1183CONFIG_PLIST=y
1184CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
index 3de5c643848c..baa97698c744 100644
--- a/arch/arm/configs/ateb9200_defconfig
+++ b/arch/arm/configs/ateb9200_defconfig
@@ -1066,7 +1066,7 @@ CONFIG_RTC_INTF_DEV=y
1066# CONFIG_RTC_DRV_PCF8563 is not set 1066# CONFIG_RTC_DRV_PCF8563 is not set
1067# CONFIG_RTC_DRV_RS5C372 is not set 1067# CONFIG_RTC_DRV_RS5C372 is not set
1068# CONFIG_RTC_DRV_M48T86 is not set 1068# CONFIG_RTC_DRV_M48T86 is not set
1069CONFIG_RTC_DRV_AT91=y 1069CONFIG_RTC_DRV_AT91RM9200=y
1070# CONFIG_RTC_DRV_TEST is not set 1070# CONFIG_RTC_DRV_TEST is not set
1071 1071
1072# 1072#
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
index 2cadd51506bb..88e5d28aeec7 100644
--- a/arch/arm/configs/csb337_defconfig
+++ b/arch/arm/configs/csb337_defconfig
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y
355# Mapping drivers for chip access 355# Mapping drivers for chip access
356# 356#
357# CONFIG_MTD_COMPLEX_MAPPINGS is not set 357# CONFIG_MTD_COMPLEX_MAPPINGS is not set
358# CONFIG_MTD_PHYSMAP is not set 358CONFIG_MTD_PHYSMAP=y
359CONFIG_MTD_PHYSMAP_START=0
360CONFIG_MTD_PHYSMAP_LEN=0
361CONFIG_MTD_PHYSMAP_BANKWIDTH=0
359# CONFIG_MTD_ARM_INTEGRATOR is not set 362# CONFIG_MTD_ARM_INTEGRATOR is not set
360# CONFIG_MTD_PLATRAM is not set 363# CONFIG_MTD_PLATRAM is not set
361CONFIG_MTD_CSB337=y
362 364
363# 365#
364# Self-contained MTD device drivers 366# Self-contained MTD device drivers
@@ -986,7 +988,7 @@ CONFIG_RTC_DRV_DS1307=y
986# CONFIG_RTC_DRV_PCF8583 is not set 988# CONFIG_RTC_DRV_PCF8583 is not set
987# CONFIG_RTC_DRV_RS5C372 is not set 989# CONFIG_RTC_DRV_RS5C372 is not set
988# CONFIG_RTC_DRV_M48T86 is not set 990# CONFIG_RTC_DRV_M48T86 is not set
989CONFIG_RTC_DRV_AT91=y 991CONFIG_RTC_DRV_AT91RM9200=y
990# CONFIG_RTC_DRV_TEST is not set 992# CONFIG_RTC_DRV_TEST is not set
991# CONFIG_RTC_DRV_V3020 is not set 993# CONFIG_RTC_DRV_V3020 is not set
992 994
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig
index 94908c1df4cf..669f035896f9 100644
--- a/arch/arm/configs/csb637_defconfig
+++ b/arch/arm/configs/csb637_defconfig
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y
355# Mapping drivers for chip access 355# Mapping drivers for chip access
356# 356#
357# CONFIG_MTD_COMPLEX_MAPPINGS is not set 357# CONFIG_MTD_COMPLEX_MAPPINGS is not set
358# CONFIG_MTD_PHYSMAP is not set 358CONFIG_MTD_PHYSMAP=y
359CONFIG_MTD_PHYSMAP_START=0
360CONFIG_MTD_PHYSMAP_LEN=0
361CONFIG_MTD_PHYSMAP_BANKWIDTH=0
359# CONFIG_MTD_ARM_INTEGRATOR is not set 362# CONFIG_MTD_ARM_INTEGRATOR is not set
360# CONFIG_MTD_PLATRAM is not set 363# CONFIG_MTD_PLATRAM is not set
361CONFIG_MTD_CSB637=y
362 364
363# 365#
364# Self-contained MTD device drivers 366# Self-contained MTD device drivers
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
index a4cdafc1548a..a0f48d54fbcc 100644
--- a/arch/arm/configs/kafa_defconfig
+++ b/arch/arm/configs/kafa_defconfig
@@ -718,7 +718,7 @@ CONFIG_RTC_INTF_DEV=y
718# CONFIG_RTC_DRV_PCF8563 is not set 718# CONFIG_RTC_DRV_PCF8563 is not set
719# CONFIG_RTC_DRV_RS5C372 is not set 719# CONFIG_RTC_DRV_RS5C372 is not set
720# CONFIG_RTC_DRV_M48T86 is not set 720# CONFIG_RTC_DRV_M48T86 is not set
721CONFIG_RTC_DRV_AT91=y 721CONFIG_RTC_DRV_AT91RM9200=y
722# CONFIG_RTC_DRV_TEST is not set 722# CONFIG_RTC_DRV_TEST is not set
723 723
724# 724#
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 3b31a33d0080..df19e3632038 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.19-rc4 3# Linux kernel version: 2.6.20
4# Fri Nov 3 17:41:31 2006 4# Thu Feb 15 11:26:24 2007
5# 5#
6CONFIG_ARM=y 6CONFIG_ARM=y
7# CONFIG_GENERIC_TIME is not set 7# CONFIG_GENERIC_TIME is not set
@@ -11,6 +11,8 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
11CONFIG_HARDIRQS_SW_RESEND=y 11CONFIG_HARDIRQS_SW_RESEND=y
12CONFIG_GENERIC_IRQ_PROBE=y 12CONFIG_GENERIC_IRQ_PROBE=y
13CONFIG_RWSEM_GENERIC_SPINLOCK=y 13CONFIG_RWSEM_GENERIC_SPINLOCK=y
14# CONFIG_ARCH_HAS_ILOG2_U32 is not set
15# CONFIG_ARCH_HAS_ILOG2_U64 is not set
14CONFIG_GENERIC_HWEIGHT=y 16CONFIG_GENERIC_HWEIGHT=y
15CONFIG_GENERIC_CALIBRATE_DELAY=y 17CONFIG_GENERIC_CALIBRATE_DELAY=y
16CONFIG_VECTORS_BASE=0xffff0000 18CONFIG_VECTORS_BASE=0xffff0000
@@ -37,13 +39,14 @@ CONFIG_SYSVIPC=y
37# CONFIG_UTS_NS is not set 39# CONFIG_UTS_NS is not set
38# CONFIG_AUDIT is not set 40# CONFIG_AUDIT is not set
39# CONFIG_IKCONFIG is not set 41# CONFIG_IKCONFIG is not set
42CONFIG_SYSFS_DEPRECATED=y
40# CONFIG_RELAY is not set 43# CONFIG_RELAY is not set
41CONFIG_INITRAMFS_SOURCE="" 44CONFIG_INITRAMFS_SOURCE=""
42CONFIG_CC_OPTIMIZE_FOR_SIZE=y 45CONFIG_CC_OPTIMIZE_FOR_SIZE=y
43CONFIG_SYSCTL=y 46CONFIG_SYSCTL=y
44# CONFIG_EMBEDDED is not set 47# CONFIG_EMBEDDED is not set
45CONFIG_UID16=y 48CONFIG_UID16=y
46# CONFIG_SYSCTL_SYSCALL is not set 49CONFIG_SYSCTL_SYSCALL=y
47CONFIG_KALLSYMS=y 50CONFIG_KALLSYMS=y
48# CONFIG_KALLSYMS_ALL is not set 51# CONFIG_KALLSYMS_ALL is not set
49# CONFIG_KALLSYMS_EXTRA_PASS is not set 52# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -76,7 +79,9 @@ CONFIG_KMOD=y
76# Block layer 79# Block layer
77# 80#
78CONFIG_BLOCK=y 81CONFIG_BLOCK=y
82# CONFIG_LBD is not set
79# CONFIG_BLK_DEV_IO_TRACE is not set 83# CONFIG_BLK_DEV_IO_TRACE is not set
84# CONFIG_LSF is not set
80 85
81# 86#
82# IO Schedulers 87# IO Schedulers
@@ -110,6 +115,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
110# CONFIG_ARCH_IMX is not set 115# CONFIG_ARCH_IMX is not set
111# CONFIG_ARCH_IOP32X is not set 116# CONFIG_ARCH_IOP32X is not set
112# CONFIG_ARCH_IOP33X is not set 117# CONFIG_ARCH_IOP33X is not set
118# CONFIG_ARCH_IOP13XX is not set
113# CONFIG_ARCH_IXP4XX is not set 119# CONFIG_ARCH_IXP4XX is not set
114# CONFIG_ARCH_IXP2000 is not set 120# CONFIG_ARCH_IXP2000 is not set
115# CONFIG_ARCH_IXP23XX is not set 121# CONFIG_ARCH_IXP23XX is not set
@@ -122,54 +128,73 @@ CONFIG_ARCH_S3C2410=y
122# CONFIG_ARCH_SHARK is not set 128# CONFIG_ARCH_SHARK is not set
123# CONFIG_ARCH_LH7A40X is not set 129# CONFIG_ARCH_LH7A40X is not set
124# CONFIG_ARCH_OMAP is not set 130# CONFIG_ARCH_OMAP is not set
131CONFIG_PLAT_S3C24XX=y
132CONFIG_CPU_S3C244X=y
133CONFIG_PM_SIMTEC=y
134# CONFIG_S3C2410_BOOT_WATCHDOG is not set
135# CONFIG_S3C2410_BOOT_ERROR_RESET is not set
136# CONFIG_S3C2410_PM_DEBUG is not set
137# CONFIG_S3C2410_PM_CHECK is not set
138CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
139CONFIG_S3C2410_DMA=y
140# CONFIG_S3C2410_DMA_DEBUG is not set
141CONFIG_MACH_SMDK=y
125 142
126# 143#
127# S3C24XX Implementations 144# S3C2400 Machines
128# 145#
129# CONFIG_MACH_AML_M5900 is not set 146CONFIG_CPU_S3C2410=y
130CONFIG_MACH_ANUBIS=y 147CONFIG_CPU_S3C2410_DMA=y
131CONFIG_MACH_OSIRIS=y 148CONFIG_S3C2410_PM=y
132CONFIG_ARCH_BAST=y 149CONFIG_S3C2410_GPIO=y
133CONFIG_BAST_PC104_IRQ=y 150CONFIG_S3C2410_CLOCK=y
151
152#
153# S3C2410 Machines
154#
155CONFIG_ARCH_SMDK2410=y
134CONFIG_ARCH_H1940=y 156CONFIG_ARCH_H1940=y
157CONFIG_PM_H1940=y
135CONFIG_MACH_N30=y 158CONFIG_MACH_N30=y
136CONFIG_MACH_SMDK=y 159CONFIG_ARCH_BAST=y
137CONFIG_ARCH_SMDK2410=y
138CONFIG_ARCH_S3C2440=y
139CONFIG_SMDK2440_CPU2440=y
140CONFIG_SMDK2440_CPU2442=y
141CONFIG_MACH_S3C2413=y
142CONFIG_MACH_SMDK2413=y
143CONFIG_MACH_VR1000=y
144CONFIG_MACH_RX3715=y
145CONFIG_MACH_OTOM=y 160CONFIG_MACH_OTOM=y
146CONFIG_MACH_NEXCODER_2440=y 161CONFIG_MACH_AML_M5900=y
147CONFIG_MACH_VSTMS=y 162CONFIG_BAST_PC104_IRQ=y
148CONFIG_S3C2410_CLOCK=y 163CONFIG_MACH_VR1000=y
149CONFIG_S3C2410_PM=y
150CONFIG_CPU_S3C2410_DMA=y
151CONFIG_CPU_S3C2410=y
152CONFIG_S3C2412_PM=y
153CONFIG_CPU_S3C2412=y 164CONFIG_CPU_S3C2412=y
154CONFIG_CPU_S3C244X=y 165CONFIG_S3C2412_DMA=y
166CONFIG_S3C2412_PM=y
167
168#
169# S3C2412 Machines
170#
171CONFIG_MACH_SMDK2413=y
172CONFIG_MACH_S3C2413=y
173CONFIG_MACH_VSTMS=y
155CONFIG_CPU_S3C2440=y 174CONFIG_CPU_S3C2440=y
175CONFIG_S3C2440_DMA=y
176
177#
178# S3C2440 Machines
179#
180CONFIG_MACH_ANUBIS=y
181CONFIG_MACH_OSIRIS=y
182CONFIG_MACH_RX3715=y
183CONFIG_ARCH_S3C2440=y
184CONFIG_MACH_NEXCODER_2440=y
185CONFIG_SMDK2440_CPU2440=y
156CONFIG_CPU_S3C2442=y 186CONFIG_CPU_S3C2442=y
157 187
158# 188#
159# S3C2410 Boot 189# S3C2442 Machines
160# 190#
161# CONFIG_S3C2410_BOOT_WATCHDOG is not set 191CONFIG_SMDK2440_CPU2442=y
162# CONFIG_S3C2410_BOOT_ERROR_RESET is not set 192CONFIG_CPU_S3C2443=y
163 193
164# 194#
165# S3C2410 Setup 195# S3C2443 Machines
166# 196#
167CONFIG_S3C2410_DMA=y 197CONFIG_MACH_SMDK2443=y
168# CONFIG_S3C2410_DMA_DEBUG is not set
169# CONFIG_S3C2410_PM_DEBUG is not set
170# CONFIG_S3C2410_PM_CHECK is not set
171CONFIG_PM_SIMTEC=y
172CONFIG_S3C2410_LOWLEVEL_UART_PORT=0
173 198
174# 199#
175# Processor Type 200# Processor Type
@@ -196,6 +221,7 @@ CONFIG_CPU_CP15_MMU=y
196# CONFIG_CPU_DCACHE_DISABLE is not set 221# CONFIG_CPU_DCACHE_DISABLE is not set
197# CONFIG_CPU_DCACHE_WRITETHROUGH is not set 222# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
198# CONFIG_CPU_CACHE_ROUND_ROBIN is not set 223# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
224# CONFIG_OUTER_CACHE is not set
199 225
200# 226#
201# Bus support 227# Bus support
@@ -303,6 +329,7 @@ CONFIG_INET_TCP_DIAG=y
303# CONFIG_TCP_CONG_ADVANCED is not set 329# CONFIG_TCP_CONG_ADVANCED is not set
304CONFIG_TCP_CONG_CUBIC=y 330CONFIG_TCP_CONG_CUBIC=y
305CONFIG_DEFAULT_TCP_CONG="cubic" 331CONFIG_DEFAULT_TCP_CONG="cubic"
332# CONFIG_TCP_MD5SIG is not set
306# CONFIG_IPV6 is not set 333# CONFIG_IPV6 is not set
307# CONFIG_INET6_XFRM_TUNNEL is not set 334# CONFIG_INET6_XFRM_TUNNEL is not set
308# CONFIG_INET6_TUNNEL is not set 335# CONFIG_INET6_TUNNEL is not set
@@ -385,6 +412,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
385# User Modules And Translation Layers 412# User Modules And Translation Layers
386# 413#
387CONFIG_MTD_CHAR=y 414CONFIG_MTD_CHAR=y
415CONFIG_MTD_BLKDEVS=y
388CONFIG_MTD_BLOCK=y 416CONFIG_MTD_BLOCK=y
389# CONFIG_FTL is not set 417# CONFIG_FTL is not set
390# CONFIG_NFTL is not set 418# CONFIG_NFTL is not set
@@ -531,6 +559,11 @@ CONFIG_BLK_DEV_IDE_BAST=y
531# CONFIG_SCSI_NETLINK is not set 559# CONFIG_SCSI_NETLINK is not set
532 560
533# 561#
562# Serial ATA (prod) and Parallel ATA (experimental) drivers
563#
564# CONFIG_ATA is not set
565
566#
534# Multi-device support (RAID and LVM) 567# Multi-device support (RAID and LVM)
535# 568#
536# CONFIG_MD is not set 569# CONFIG_MD is not set
@@ -682,7 +715,7 @@ CONFIG_SERIAL_NONSTANDARD=y
682# CONFIG_DIGIEPCA is not set 715# CONFIG_DIGIEPCA is not set
683# CONFIG_MOXA_INTELLIO is not set 716# CONFIG_MOXA_INTELLIO is not set
684# CONFIG_MOXA_SMARTIO is not set 717# CONFIG_MOXA_SMARTIO is not set
685# CONFIG_ISI is not set 718# CONFIG_MOXA_SMARTIO_NEW is not set
686# CONFIG_SYNCLINKMP is not set 719# CONFIG_SYNCLINKMP is not set
687# CONFIG_N_HDLC is not set 720# CONFIG_N_HDLC is not set
688# CONFIG_RISCOM8 is not set 721# CONFIG_RISCOM8 is not set
@@ -700,13 +733,14 @@ CONFIG_SERIAL_8250_NR_UARTS=8
700CONFIG_SERIAL_8250_RUNTIME_UARTS=4 733CONFIG_SERIAL_8250_RUNTIME_UARTS=4
701CONFIG_SERIAL_8250_EXTENDED=y 734CONFIG_SERIAL_8250_EXTENDED=y
702CONFIG_SERIAL_8250_MANY_PORTS=y 735CONFIG_SERIAL_8250_MANY_PORTS=y
703CONFIG_SERIAL_8250_SHARE_IRQ=y
704# CONFIG_SERIAL_8250_DETECT_IRQ is not set
705# CONFIG_SERIAL_8250_RSA is not set
706# CONFIG_SERIAL_8250_FOURPORT is not set 736# CONFIG_SERIAL_8250_FOURPORT is not set
707# CONFIG_SERIAL_8250_ACCENT is not set 737# CONFIG_SERIAL_8250_ACCENT is not set
708# CONFIG_SERIAL_8250_BOCA is not set 738# CONFIG_SERIAL_8250_BOCA is not set
739# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set
709# CONFIG_SERIAL_8250_HUB6 is not set 740# CONFIG_SERIAL_8250_HUB6 is not set
741CONFIG_SERIAL_8250_SHARE_IRQ=y
742# CONFIG_SERIAL_8250_DETECT_IRQ is not set
743# CONFIG_SERIAL_8250_RSA is not set
710 744
711# 745#
712# Non-8250 serial port support 746# Non-8250 serial port support
@@ -755,10 +789,6 @@ CONFIG_HW_RANDOM=y
755# CONFIG_NVRAM is not set 789# CONFIG_NVRAM is not set
756# CONFIG_DTLK is not set 790# CONFIG_DTLK is not set
757# CONFIG_R3964 is not set 791# CONFIG_R3964 is not set
758
759#
760# Ftape, the floppy tape device driver
761#
762# CONFIG_RAW_DRIVER is not set 792# CONFIG_RAW_DRIVER is not set
763 793
764# 794#
@@ -863,6 +893,7 @@ CONFIG_SENSORS_LM85=m
863# CONFIG_SENSORS_LM92 is not set 893# CONFIG_SENSORS_LM92 is not set
864# CONFIG_SENSORS_MAX1619 is not set 894# CONFIG_SENSORS_MAX1619 is not set
865# CONFIG_SENSORS_PC87360 is not set 895# CONFIG_SENSORS_PC87360 is not set
896# CONFIG_SENSORS_PC87427 is not set
866# CONFIG_SENSORS_SMSC47M1 is not set 897# CONFIG_SENSORS_SMSC47M1 is not set
867# CONFIG_SENSORS_SMSC47M192 is not set 898# CONFIG_SENSORS_SMSC47M192 is not set
868# CONFIG_SENSORS_SMSC47B397 is not set 899# CONFIG_SENSORS_SMSC47B397 is not set
@@ -870,6 +901,7 @@ CONFIG_SENSORS_LM85=m
870# CONFIG_SENSORS_W83781D is not set 901# CONFIG_SENSORS_W83781D is not set
871# CONFIG_SENSORS_W83791D is not set 902# CONFIG_SENSORS_W83791D is not set
872# CONFIG_SENSORS_W83792D is not set 903# CONFIG_SENSORS_W83792D is not set
904# CONFIG_SENSORS_W83793 is not set
873# CONFIG_SENSORS_W83L785TS is not set 905# CONFIG_SENSORS_W83L785TS is not set
874# CONFIG_SENSORS_W83627HF is not set 906# CONFIG_SENSORS_W83627HF is not set
875# CONFIG_SENSORS_W83627EHF is not set 907# CONFIG_SENSORS_W83627EHF is not set
@@ -952,6 +984,11 @@ CONFIG_FONT_8x16=y
952# CONFIG_SOUND is not set 984# CONFIG_SOUND is not set
953 985
954# 986#
987# HID Devices
988#
989CONFIG_HID=y
990
991#
955# USB support 992# USB support
956# 993#
957CONFIG_USB_ARCH_HAS_HCD=y 994CONFIG_USB_ARCH_HAS_HCD=y
@@ -1028,6 +1065,7 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
1028# CONFIG_USB_KAWETH is not set 1065# CONFIG_USB_KAWETH is not set
1029# CONFIG_USB_PEGASUS is not set 1066# CONFIG_USB_PEGASUS is not set
1030# CONFIG_USB_RTL8150 is not set 1067# CONFIG_USB_RTL8150 is not set
1068# CONFIG_USB_USBNET_MII is not set
1031# CONFIG_USB_USBNET is not set 1069# CONFIG_USB_USBNET is not set
1032CONFIG_USB_MON=y 1070CONFIG_USB_MON=y
1033 1071
@@ -1179,9 +1217,6 @@ CONFIG_RAMFS=y
1179# CONFIG_BEFS_FS is not set 1217# CONFIG_BEFS_FS is not set
1180# CONFIG_BFS_FS is not set 1218# CONFIG_BFS_FS is not set
1181# CONFIG_EFS_FS is not set 1219# CONFIG_EFS_FS is not set
1182CONFIG_JFFS_FS=y
1183CONFIG_JFFS_FS_VERBOSE=0
1184# CONFIG_JFFS_PROC_FS is not set
1185CONFIG_JFFS2_FS=y 1220CONFIG_JFFS2_FS=y
1186CONFIG_JFFS2_FS_DEBUG=0 1221CONFIG_JFFS2_FS_DEBUG=0
1187CONFIG_JFFS2_FS_WRITEBUFFER=y 1222CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1191,7 +1226,7 @@ CONFIG_JFFS2_FS_WRITEBUFFER=y
1191CONFIG_JFFS2_ZLIB=y 1226CONFIG_JFFS2_ZLIB=y
1192CONFIG_JFFS2_RTIME=y 1227CONFIG_JFFS2_RTIME=y
1193# CONFIG_JFFS2_RUBIN is not set 1228# CONFIG_JFFS2_RUBIN is not set
1194# CONFIG_CRAMFS is not set 1229CONFIG_CRAMFS=y
1195# CONFIG_VXFS_FS is not set 1230# CONFIG_VXFS_FS is not set
1196# CONFIG_HPFS_FS is not set 1231# CONFIG_HPFS_FS is not set
1197# CONFIG_QNX4FS_FS is not set 1232# CONFIG_QNX4FS_FS is not set
@@ -1285,6 +1320,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
1285# CONFIG_NLS_UTF8 is not set 1320# CONFIG_NLS_UTF8 is not set
1286 1321
1287# 1322#
1323# Distributed Lock Manager
1324#
1325# CONFIG_DLM is not set
1326
1327#
1288# Profiling support 1328# Profiling support
1289# 1329#
1290# CONFIG_PROFILING is not set 1330# CONFIG_PROFILING is not set
@@ -1296,6 +1336,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
1296CONFIG_ENABLE_MUST_CHECK=y 1336CONFIG_ENABLE_MUST_CHECK=y
1297CONFIG_MAGIC_SYSRQ=y 1337CONFIG_MAGIC_SYSRQ=y
1298# CONFIG_UNUSED_SYMBOLS is not set 1338# CONFIG_UNUSED_SYMBOLS is not set
1339# CONFIG_DEBUG_FS is not set
1340# CONFIG_HEADERS_CHECK is not set
1299CONFIG_DEBUG_KERNEL=y 1341CONFIG_DEBUG_KERNEL=y
1300CONFIG_LOG_BUF_SHIFT=16 1342CONFIG_LOG_BUF_SHIFT=16
1301CONFIG_DETECT_SOFTLOCKUP=y 1343CONFIG_DETECT_SOFTLOCKUP=y
@@ -1311,12 +1353,10 @@ CONFIG_DEBUG_MUTEXES=y
1311# CONFIG_DEBUG_KOBJECT is not set 1353# CONFIG_DEBUG_KOBJECT is not set
1312CONFIG_DEBUG_BUGVERBOSE=y 1354CONFIG_DEBUG_BUGVERBOSE=y
1313CONFIG_DEBUG_INFO=y 1355CONFIG_DEBUG_INFO=y
1314# CONFIG_DEBUG_FS is not set
1315# CONFIG_DEBUG_VM is not set 1356# CONFIG_DEBUG_VM is not set
1316# CONFIG_DEBUG_LIST is not set 1357# CONFIG_DEBUG_LIST is not set
1317CONFIG_FRAME_POINTER=y 1358CONFIG_FRAME_POINTER=y
1318CONFIG_FORCED_INLINING=y 1359CONFIG_FORCED_INLINING=y
1319# CONFIG_HEADERS_CHECK is not set
1320# CONFIG_RCU_TORTURE_TEST is not set 1360# CONFIG_RCU_TORTURE_TEST is not set
1321CONFIG_DEBUG_USER=y 1361CONFIG_DEBUG_USER=y
1322# CONFIG_DEBUG_ERRORS is not set 1362# CONFIG_DEBUG_ERRORS is not set
@@ -1339,6 +1379,7 @@ CONFIG_DEBUG_S3C2410_UART=0
1339# 1379#
1340# Library routines 1380# Library routines
1341# 1381#
1382CONFIG_BITREVERSE=y
1342# CONFIG_CRC_CCITT is not set 1383# CONFIG_CRC_CCITT is not set
1343# CONFIG_CRC16 is not set 1384# CONFIG_CRC16 is not set
1344CONFIG_CRC32=y 1385CONFIG_CRC32=y
@@ -1346,3 +1387,4 @@ CONFIG_CRC32=y
1346CONFIG_ZLIB_INFLATE=y 1387CONFIG_ZLIB_INFLATE=y
1347CONFIG_ZLIB_DEFLATE=y 1388CONFIG_ZLIB_DEFLATE=y
1348CONFIG_PLIST=y 1389CONFIG_PLIST=y
1390CONFIG_IOMAP_COPY=y
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index ab06a86e85d5..d5002889773e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARTHUR) += arthur.o
19obj-$(CONFIG_ISA_DMA) += dma-isa.o 19obj-$(CONFIG_ISA_DMA) += dma-isa.o
20obj-$(CONFIG_PCI) += bios32.o isa.o 20obj-$(CONFIG_PCI) += bios32.o isa.o
21obj-$(CONFIG_SMP) += smp.o 21obj-$(CONFIG_SMP) += smp.o
22obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
22obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o 23obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o
23 24
24obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o 25obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index f7598cbc7ec5..ae89cdd82b16 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -356,6 +356,7 @@
356 CALL(sys_move_pages) 356 CALL(sys_move_pages)
357/* 345 */ CALL(sys_getcpu) 357/* 345 */ CALL(sys_getcpu)
358 CALL(sys_ni_syscall) /* eventually epoll_pwait */ 358 CALL(sys_ni_syscall) /* eventually epoll_pwait */
359 CALL(sys_kexec_load)
359#ifndef syscalls_counted 360#ifndef syscalls_counted
360.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls 361.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
361#define syscalls_counted 362#define syscalls_counted
diff --git a/arch/arm/kernel/crunch.c b/arch/arm/kernel/crunch.c
index cec83783206e..627d79414c9d 100644
--- a/arch/arm/kernel/crunch.c
+++ b/arch/arm/kernel/crunch.c
@@ -75,6 +75,7 @@ static struct notifier_block crunch_notifier_block = {
75static int __init crunch_init(void) 75static int __init crunch_init(void)
76{ 76{
77 thread_register_notifier(&crunch_notifier_block); 77 thread_register_notifier(&crunch_notifier_block);
78 elf_hwcap |= HWCAP_CRUNCH;
78 79
79 return 0; 80 return 0;
80} 81}
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 71257e3d513f..f1c0fb974177 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -1009,7 +1009,7 @@ ecard_probe(int slot, card_type_t type)
1009 ec->fiqmask = 4; 1009 ec->fiqmask = 4;
1010 } 1010 }
1011 1011
1012 for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++) 1012 for (i = 0; i < ARRAY_SIZE(blacklist); i++)
1013 if (blacklist[i].manufacturer == ec->cid.manufacturer && 1013 if (blacklist[i].manufacturer == ec->cid.manufacturer &&
1014 blacklist[i].product == ec->cid.product) { 1014 blacklist[i].product == ec->cid.product) {
1015 ec->card_desc = blacklist[i].type; 1015 ec->card_desc = blacklist[i].type;
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
new file mode 100644
index 000000000000..863c66454f2b
--- /dev/null
+++ b/arch/arm/kernel/machine_kexec.c
@@ -0,0 +1,78 @@
1/*
2 * machine_kexec.c - handle transition of Linux booting another kernel
3 */
4
5#include <linux/mm.h>
6#include <linux/kexec.h>
7#include <linux/delay.h>
8#include <linux/reboot.h>
9#include <asm/pgtable.h>
10#include <asm/pgalloc.h>
11#include <asm/mmu_context.h>
12#include <asm/io.h>
13#include <asm/cacheflush.h>
14#include <asm/mach-types.h>
15
16const extern unsigned char relocate_new_kernel[];
17const extern unsigned int relocate_new_kernel_size;
18
19extern void setup_mm_for_reboot(char mode);
20
21extern unsigned long kexec_start_address;
22extern unsigned long kexec_indirection_page;
23extern unsigned long kexec_mach_type;
24
25/*
26 * Provide a dummy crash_notes definition while crash dump arrives to arm.
27 * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
28 */
29
30int machine_kexec_prepare(struct kimage *image)
31{
32 return 0;
33}
34
35void machine_kexec_cleanup(struct kimage *image)
36{
37}
38
39void machine_shutdown(void)
40{
41}
42
43void machine_crash_shutdown(struct pt_regs *regs)
44{
45}
46
47void machine_kexec(struct kimage *image)
48{
49 unsigned long page_list;
50 unsigned long reboot_code_buffer_phys;
51 void *reboot_code_buffer;
52
53
54 page_list = image->head & PAGE_MASK;
55
56 /* we need both effective and real address here */
57 reboot_code_buffer_phys =
58 page_to_pfn(image->control_code_page) << PAGE_SHIFT;
59 reboot_code_buffer = page_address(image->control_code_page);
60
61 /* Prepare parameters for reboot_code_buffer*/
62 kexec_start_address = image->start;
63 kexec_indirection_page = page_list;
64 kexec_mach_type = machine_arch_type;
65
66 /* copy our kernel relocation code to the control code page */
67 memcpy(reboot_code_buffer,
68 relocate_new_kernel, relocate_new_kernel_size);
69
70
71 flush_icache_range((unsigned long) reboot_code_buffer,
72 (unsigned long) reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
73 printk(KERN_INFO "Bye!\n");
74
75 cpu_proc_fin();
76 setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
77 cpu_reset(reboot_code_buffer_phys);
78}
diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
new file mode 100644
index 000000000000..7baadae7cb27
--- /dev/null
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -0,0 +1,74 @@
1/*
2 * relocate_kernel.S - put the kernel image in place to boot
3 */
4
5#include <asm/kexec.h>
6
7 .globl relocate_new_kernel
8relocate_new_kernel:
9
10 ldr r0,kexec_indirection_page
11 ldr r1,kexec_start_address
12
13
140: /* top, read another word for the indirection page */
15 ldr r3, [r0],#4
16
17 /* Is it a destination page. Put destination address to r4 */
18 tst r3,#1,0
19 beq 1f
20 bic r4,r3,#1
21 b 0b
221:
23 /* Is it an indirection page */
24 tst r3,#2,0
25 beq 1f
26 bic r0,r3,#2
27 b 0b
281:
29
30 /* are we done ? */
31 tst r3,#4,0
32 beq 1f
33 b 2f
34
351:
36 /* is it source ? */
37 tst r3,#8,0
38 beq 0b
39 bic r3,r3,#8
40 mov r6,#1024
419:
42 ldr r5,[r3],#4
43 str r5,[r4],#4
44 subs r6,r6,#1
45 bne 9b
46 b 0b
47
482:
49 /* Jump to relocated kernel */
50 mov lr,r1
51 mov r0,#0
52 ldr r1,kexec_mach_type
53 mov r2,#0
54 mov pc,lr
55
56 .globl kexec_start_address
57kexec_start_address:
58 .long 0x0
59
60 .globl kexec_indirection_page
61kexec_indirection_page:
62 .long 0x0
63
64 .globl kexec_mach_type
65kexec_mach_type:
66 .long 0x0
67
68relocate_new_kernel_end:
69
70 .globl relocate_new_kernel_size
71relocate_new_kernel_size:
72 .long relocate_new_kernel_end - relocate_new_kernel
73
74
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bbab134cd82d..243aea458057 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -88,6 +88,9 @@ struct cpu_user_fns cpu_user;
88#ifdef MULTI_CACHE 88#ifdef MULTI_CACHE
89struct cpu_cache_fns cpu_cache; 89struct cpu_cache_fns cpu_cache;
90#endif 90#endif
91#ifdef CONFIG_OUTER_CACHE
92struct outer_cache_fns outer_cache;
93#endif
91 94
92struct stack { 95struct stack {
93 u32 irq[3]; 96 u32 irq[3];
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 3c8cdcfe8d4a..3825acd6687d 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -40,12 +40,14 @@
40 */ 40 */
41struct sys_timer *system_timer; 41struct sys_timer *system_timer;
42 42
43#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
43/* this needs a better home */ 44/* this needs a better home */
44DEFINE_SPINLOCK(rtc_lock); 45DEFINE_SPINLOCK(rtc_lock);
45 46
46#ifdef CONFIG_SA1100_RTC_MODULE 47#ifdef CONFIG_RTC_DRV_CMOS_MODULE
47EXPORT_SYMBOL(rtc_lock); 48EXPORT_SYMBOL(rtc_lock);
48#endif 49#endif
50#endif /* pc-style 'CMOS' RTC support */
49 51
50/* change this if you have some constant time drift */ 52/* change this if you have some constant time drift */
51#define USECS_PER_JIFFY (1000000/HZ) 53#define USECS_PER_JIFFY (1000000/HZ)
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91/Kconfig
index 9f11db8af233..bf0d96272e3a 100644
--- a/arch/arm/mach-at91rm9200/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -9,11 +9,14 @@ config ARCH_AT91RM9200
9 bool "AT91RM9200" 9 bool "AT91RM9200"
10 10
11config ARCH_AT91SAM9260 11config ARCH_AT91SAM9260
12 bool "AT91SAM9260" 12 bool "AT91SAM9260 or AT91SAM9XE"
13 13
14config ARCH_AT91SAM9261 14config ARCH_AT91SAM9261
15 bool "AT91SAM9261" 15 bool "AT91SAM9261"
16 16
17config ARCH_AT91SAM9263
18 bool "AT91SAM9263"
19
17endchoice 20endchoice
18 21
19# ---------------------------------------------------------- 22# ----------------------------------------------------------
@@ -90,13 +93,22 @@ endif
90 93
91if ARCH_AT91SAM9260 94if ARCH_AT91SAM9260
92 95
93comment "AT91SAM9260 Board Type" 96comment "AT91SAM9260 Variants"
97
98config ARCH_AT91SAM9260_SAM9XE
99 bool "AT91SAM9XE"
100 depends on ARCH_AT91SAM9260
101 help
102 Select this if you are using Atmel's AT91SAM9XE System-on-Chip.
103 They are basicaly AT91SAM9260s with various sizes of embedded Flash.
104
105comment "AT91SAM9260 / AT91SAM9XE Board Type"
94 106
95config MACH_AT91SAM9260EK 107config MACH_AT91SAM9260EK
96 bool "Atmel AT91SAM9260-EK Evaluation Kit" 108 bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit"
97 depends on ARCH_AT91SAM9260 109 depends on ARCH_AT91SAM9260
98 help 110 help
99 Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit. 111 Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit
100 <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933> 112 <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933>
101 113
102endif 114endif
@@ -118,17 +130,32 @@ endif
118 130
119# ---------------------------------------------------------- 131# ----------------------------------------------------------
120 132
133if ARCH_AT91SAM9263
134
135comment "AT91SAM9263 Board Type"
136
137config MACH_AT91SAM9263EK
138 bool "Atmel AT91SAM9263-EK Evaluation Kit"
139 depends on ARCH_AT91SAM9263
140 help
141 Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit.
142 <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057>
143
144endif
145
146# ----------------------------------------------------------
147
121comment "AT91 Board Options" 148comment "AT91 Board Options"
122 149
123config MTD_AT91_DATAFLASH_CARD 150config MTD_AT91_DATAFLASH_CARD
124 bool "Enable DataFlash Card support" 151 bool "Enable DataFlash Card support"
125 depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK) 152 depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
126 help 153 help
127 Enable support for the DataFlash card. 154 Enable support for the DataFlash card.
128 155
129config MTD_NAND_AT91_BUSWIDTH_16 156config MTD_NAND_AT91_BUSWIDTH_16
130 bool "Enable 16-bit data bus interface to NAND flash" 157 bool "Enable 16-bit data bus interface to NAND flash"
131 depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK) 158 depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK)
132 help 159 help
133 On AT91SAM926x boards both types of NAND flash can be present 160 On AT91SAM926x boards both types of NAND flash can be present
134 (8 and 16 bit data bus width). 161 (8 and 16 bit data bus width).
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91/Makefile
index cf777007847a..05de6cdc88f1 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_PM) += pm.o
13obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o 13obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
14obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o 14obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o
15obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o 15obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o
16obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o
16 17
17# AT91RM9200 board-specific support 18# AT91RM9200 board-specific support
18obj-$(CONFIG_MACH_ONEARM) += board-1arm.o 19obj-$(CONFIG_MACH_ONEARM) += board-1arm.o
@@ -31,6 +32,9 @@ obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o
31# AT91SAM9261 board-specific support 32# AT91SAM9261 board-specific support
32obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o 33obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
33 34
35# AT91SAM9263 board-specific support
36obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o
37
34# LEDs support 38# LEDs support
35led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o 39led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o
36led-$(CONFIG_MACH_AT91RM9200EK) += leds.o 40led-$(CONFIG_MACH_AT91RM9200EK) += leds.o
diff --git a/arch/arm/mach-at91rm9200/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
index e667dcc7cd34..e667dcc7cd34 100644
--- a/arch/arm/mach-at91rm9200/Makefile.boot
+++ b/arch/arm/mach-at91/Makefile.boot
diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index a92e9a495b07..2ddcdd69df7d 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/mach-at91rm9200/at91rm9200.c 2 * arch/arm/mach-at91/at91rm9200.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * 5 *
@@ -117,6 +117,36 @@ static struct clk pioD_clk = {
117 .pmc_mask = 1 << AT91RM9200_ID_PIOD, 117 .pmc_mask = 1 << AT91RM9200_ID_PIOD,
118 .type = CLK_TYPE_PERIPHERAL, 118 .type = CLK_TYPE_PERIPHERAL,
119}; 119};
120static struct clk tc0_clk = {
121 .name = "tc0_clk",
122 .pmc_mask = 1 << AT91RM9200_ID_TC0,
123 .type = CLK_TYPE_PERIPHERAL,
124};
125static struct clk tc1_clk = {
126 .name = "tc1_clk",
127 .pmc_mask = 1 << AT91RM9200_ID_TC1,
128 .type = CLK_TYPE_PERIPHERAL,
129};
130static struct clk tc2_clk = {
131 .name = "tc2_clk",
132 .pmc_mask = 1 << AT91RM9200_ID_TC2,
133 .type = CLK_TYPE_PERIPHERAL,
134};
135static struct clk tc3_clk = {
136 .name = "tc3_clk",
137 .pmc_mask = 1 << AT91RM9200_ID_TC3,
138 .type = CLK_TYPE_PERIPHERAL,
139};
140static struct clk tc4_clk = {
141 .name = "tc4_clk",
142 .pmc_mask = 1 << AT91RM9200_ID_TC4,
143 .type = CLK_TYPE_PERIPHERAL,
144};
145static struct clk tc5_clk = {
146 .name = "tc5_clk",
147 .pmc_mask = 1 << AT91RM9200_ID_TC5,
148 .type = CLK_TYPE_PERIPHERAL,
149};
120 150
121static struct clk *periph_clocks[] __initdata = { 151static struct clk *periph_clocks[] __initdata = {
122 &pioA_clk, 152 &pioA_clk,
@@ -132,7 +162,12 @@ static struct clk *periph_clocks[] __initdata = {
132 &twi_clk, 162 &twi_clk,
133 &spi_clk, 163 &spi_clk,
134 // ssc 0 .. ssc2 164 // ssc 0 .. ssc2
135 // tc0 .. tc5 165 &tc0_clk,
166 &tc1_clk,
167 &tc2_clk,
168 &tc3_clk,
169 &tc4_clk,
170 &tc5_clk,
136 &ohci_clk, 171 &ohci_clk,
137 &ether_clk, 172 &ether_clk,
138 // irq0 .. irq6 173 // irq0 .. irq6
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 57fac7203fe4..2624a4f22d61 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/mach-at91rm9200/at91rm9200_devices.c 2 * arch/arm/mach-at91/at91rm9200_devices.c
3 * 3 *
4 * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> 4 * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
5 * Copyright (C) 2005 David Brownell 5 * Copyright (C) 2005 David Brownell
@@ -315,7 +315,7 @@ static struct platform_device at91rm9200_mmc_device = {
315 .num_resources = ARRAY_SIZE(mmc_resources), 315 .num_resources = ARRAY_SIZE(mmc_resources),
316}; 316};
317 317
318void __init at91_add_device_mmc(struct at91_mmc_data *data) 318void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
319{ 319{
320 if (!data) 320 if (!data)
321 return; 321 return;
@@ -361,7 +361,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
361 platform_device_register(&at91rm9200_mmc_device); 361 platform_device_register(&at91rm9200_mmc_device);
362} 362}
363#else 363#else
364void __init at91_add_device_mmc(struct at91_mmc_data *data) {} 364void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
365#endif 365#endif
366 366
367 367
@@ -594,6 +594,10 @@ u8 at91_leds_timer;
594 594
595void __init at91_init_leds(u8 cpu_led, u8 timer_led) 595void __init at91_init_leds(u8 cpu_led, u8 timer_led)
596{ 596{
597 /* Enable GPIO to access the LEDs */
598 at91_set_gpio_output(cpu_led, 1);
599 at91_set_gpio_output(timer_led, 1);
600
597 at91_leds_cpu = cpu_led; 601 at91_leds_cpu = cpu_led;
598 at91_leds_timer = timer_led; 602 at91_leds_timer = timer_led;
599} 603}
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index b999e192a7e9..949199a244c7 100644
--- a/arch/arm/mach-at91rm9200/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c 2 * linux/arch/arm/mach-at91/at91rm9200_time.c
3 * 3 *
4 * Copyright (C) 2003 SAN People 4 * Copyright (C) 2003 SAN People
5 * Copyright (C) 2003 ATMEL 5 * Copyright (C) 2003 ATMEL
diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index b14871adc300..6ea41d8266cb 100644
--- a/arch/arm/mach-at91rm9200/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/mach-at91rm9200/at91sam9260.c 2 * arch/arm/mach-at91/at91sam9260.c
3 * 3 *
4 * Copyright (C) 2006 SAN People 4 * Copyright (C) 2006 SAN People
5 * 5 *
@@ -14,6 +14,7 @@
14 14
15#include <asm/mach/arch.h> 15#include <asm/mach/arch.h>
16#include <asm/mach/map.h> 16#include <asm/mach/map.h>
17#include <asm/arch/cpu.h>
17#include <asm/arch/at91sam9260.h> 18#include <asm/arch/at91sam9260.h>
18#include <asm/arch/at91_pmc.h> 19#include <asm/arch/at91_pmc.h>
19#include <asm/arch/at91_rstc.h> 20#include <asm/arch/at91_rstc.h>
@@ -27,7 +28,11 @@ static struct map_desc at91sam9260_io_desc[] __initdata = {
27 .pfn = __phys_to_pfn(AT91_BASE_SYS), 28 .pfn = __phys_to_pfn(AT91_BASE_SYS),
28 .length = SZ_16K, 29 .length = SZ_16K,
29 .type = MT_DEVICE, 30 .type = MT_DEVICE,
30 }, { 31 }
32};
33
34static struct map_desc at91sam9260_sram_desc[] __initdata = {
35 {
31 .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE, 36 .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE,
32 .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE), 37 .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE),
33 .length = AT91SAM9260_SRAM0_SIZE, 38 .length = AT91SAM9260_SRAM0_SIZE,
@@ -37,7 +42,14 @@ static struct map_desc at91sam9260_io_desc[] __initdata = {
37 .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE), 42 .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE),
38 .length = AT91SAM9260_SRAM1_SIZE, 43 .length = AT91SAM9260_SRAM1_SIZE,
39 .type = MT_DEVICE, 44 .type = MT_DEVICE,
40 }, 45 }
46};
47
48static struct map_desc at91sam9xe_sram_desc[] __initdata = {
49 {
50 .pfn = __phys_to_pfn(AT91SAM9XE_SRAM_BASE),
51 .type = MT_DEVICE,
52 }
41}; 53};
42 54
43/* -------------------------------------------------------------------- 55/* --------------------------------------------------------------------
@@ -107,13 +119,28 @@ static struct clk spi1_clk = {
107 .pmc_mask = 1 << AT91SAM9260_ID_SPI1, 119 .pmc_mask = 1 << AT91SAM9260_ID_SPI1,
108 .type = CLK_TYPE_PERIPHERAL, 120 .type = CLK_TYPE_PERIPHERAL,
109}; 121};
122static struct clk tc0_clk = {
123 .name = "tc0_clk",
124 .pmc_mask = 1 << AT91SAM9260_ID_TC0,
125 .type = CLK_TYPE_PERIPHERAL,
126};
127static struct clk tc1_clk = {
128 .name = "tc1_clk",
129 .pmc_mask = 1 << AT91SAM9260_ID_TC1,
130 .type = CLK_TYPE_PERIPHERAL,
131};
132static struct clk tc2_clk = {
133 .name = "tc2_clk",
134 .pmc_mask = 1 << AT91SAM9260_ID_TC2,
135 .type = CLK_TYPE_PERIPHERAL,
136};
110static struct clk ohci_clk = { 137static struct clk ohci_clk = {
111 .name = "ohci_clk", 138 .name = "ohci_clk",
112 .pmc_mask = 1 << AT91SAM9260_ID_UHP, 139 .pmc_mask = 1 << AT91SAM9260_ID_UHP,
113 .type = CLK_TYPE_PERIPHERAL, 140 .type = CLK_TYPE_PERIPHERAL,
114}; 141};
115static struct clk ether_clk = { 142static struct clk macb_clk = {
116 .name = "ether_clk", 143 .name = "macb_clk",
117 .pmc_mask = 1 << AT91SAM9260_ID_EMAC, 144 .pmc_mask = 1 << AT91SAM9260_ID_EMAC,
118 .type = CLK_TYPE_PERIPHERAL, 145 .type = CLK_TYPE_PERIPHERAL,
119}; 146};
@@ -137,6 +164,21 @@ static struct clk usart5_clk = {
137 .pmc_mask = 1 << AT91SAM9260_ID_US5, 164 .pmc_mask = 1 << AT91SAM9260_ID_US5,
138 .type = CLK_TYPE_PERIPHERAL, 165 .type = CLK_TYPE_PERIPHERAL,
139}; 166};
167static struct clk tc3_clk = {
168 .name = "tc3_clk",
169 .pmc_mask = 1 << AT91SAM9260_ID_TC3,
170 .type = CLK_TYPE_PERIPHERAL,
171};
172static struct clk tc4_clk = {
173 .name = "tc4_clk",
174 .pmc_mask = 1 << AT91SAM9260_ID_TC4,
175 .type = CLK_TYPE_PERIPHERAL,
176};
177static struct clk tc5_clk = {
178 .name = "tc5_clk",
179 .pmc_mask = 1 << AT91SAM9260_ID_TC5,
180 .type = CLK_TYPE_PERIPHERAL,
181};
140 182
141static struct clk *periph_clocks[] __initdata = { 183static struct clk *periph_clocks[] __initdata = {
142 &pioA_clk, 184 &pioA_clk,
@@ -152,14 +194,18 @@ static struct clk *periph_clocks[] __initdata = {
152 &spi0_clk, 194 &spi0_clk,
153 &spi1_clk, 195 &spi1_clk,
154 // ssc 196 // ssc
155 // tc0 .. tc2 197 &tc0_clk,
198 &tc1_clk,
199 &tc2_clk,
156 &ohci_clk, 200 &ohci_clk,
157 &ether_clk, 201 &macb_clk,
158 &isi_clk, 202 &isi_clk,
159 &usart3_clk, 203 &usart3_clk,
160 &usart4_clk, 204 &usart4_clk,
161 &usart5_clk, 205 &usart5_clk,
162 // tc3 .. tc5 206 &tc3_clk,
207 &tc4_clk,
208 &tc5_clk,
163 // irq0 .. irq2 209 // irq0 .. irq2
164}; 210};
165 211
@@ -213,7 +259,7 @@ static struct at91_gpio_bank at91sam9260_gpio[] = {
213 259
214static void at91sam9260_reset(void) 260static void at91sam9260_reset(void)
215{ 261{
216 at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); 262 at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
217} 263}
218 264
219 265
@@ -221,11 +267,37 @@ static void at91sam9260_reset(void)
221 * AT91SAM9260 processor initialization 267 * AT91SAM9260 processor initialization
222 * -------------------------------------------------------------------- */ 268 * -------------------------------------------------------------------- */
223 269
270static void __init at91sam9xe_initialize(void)
271{
272 unsigned long cidr, sram_size;
273
274 cidr = at91_sys_read(AT91_DBGU_CIDR);
275
276 switch (cidr & AT91_CIDR_SRAMSIZ) {
277 case AT91_CIDR_SRAMSIZ_32K:
278 sram_size = 2 * SZ_16K;
279 break;
280 case AT91_CIDR_SRAMSIZ_16K:
281 default:
282 sram_size = SZ_16K;
283 }
284
285 at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size;
286 at91sam9xe_sram_desc->length = sram_size;
287
288 iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
289}
290
224void __init at91sam9260_initialize(unsigned long main_clock) 291void __init at91sam9260_initialize(unsigned long main_clock)
225{ 292{
226 /* Map peripherals */ 293 /* Map peripherals */
227 iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); 294 iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
228 295
296 if (cpu_is_at91sam9xe())
297 at91sam9xe_initialize();
298 else
299 iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
300
229 at91_arch_reset = at91sam9260_reset; 301 at91_arch_reset = at91sam9260_reset;
230 at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) 302 at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
231 | (1 << AT91SAM9260_ID_IRQ2); 303 | (1 << AT91SAM9260_ID_IRQ2);
diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index f42d3a40ec3c..f7d342ccbebf 100644
--- a/arch/arm/mach-at91rm9200/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/mach-at91rm9200/at91sam9260_devices.c 2 * arch/arm/mach-at91/at91sam9260_devices.c
3 * 3 *
4 * Copyright (C) 2006 Atmel 4 * Copyright (C) 2006 Atmel
5 * 5 *
@@ -128,7 +128,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
128 128
129#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) 129#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
130static u64 eth_dmamask = 0xffffffffUL; 130static u64 eth_dmamask = 0xffffffffUL;
131static struct eth_platform_data eth_data; 131static struct at91_eth_data eth_data;
132 132
133static struct resource eth_resources[] = { 133static struct resource eth_resources[] = {
134 [0] = { 134 [0] = {
@@ -155,7 +155,7 @@ static struct platform_device at91sam9260_eth_device = {
155 .num_resources = ARRAY_SIZE(eth_resources), 155 .num_resources = ARRAY_SIZE(eth_resources),
156}; 156};
157 157
158void __init at91_add_device_eth(struct eth_platform_data *data) 158void __init at91_add_device_eth(struct at91_eth_data *data)
159{ 159{
160 if (!data) 160 if (!data)
161 return; 161 return;
@@ -192,7 +192,7 @@ void __init at91_add_device_eth(struct eth_platform_data *data)
192 platform_device_register(&at91sam9260_eth_device); 192 platform_device_register(&at91sam9260_eth_device);
193} 193}
194#else 194#else
195void __init at91_add_device_eth(struct eth_platform_data *data) {} 195void __init at91_add_device_eth(struct at91_eth_data *data) {}
196#endif 196#endif
197 197
198 198
@@ -229,7 +229,7 @@ static struct platform_device at91sam9260_mmc_device = {
229 .num_resources = ARRAY_SIZE(mmc_resources), 229 .num_resources = ARRAY_SIZE(mmc_resources),
230}; 230};
231 231
232void __init at91_add_device_mmc(struct at91_mmc_data *data) 232void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
233{ 233{
234 if (!data) 234 if (!data)
235 return; 235 return;
@@ -275,7 +275,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
275 platform_device_register(&at91sam9260_mmc_device); 275 platform_device_register(&at91sam9260_mmc_device);
276} 276}
277#else 277#else
278void __init at91_add_device_mmc(struct at91_mmc_data *data) {} 278void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
279#endif 279#endif
280 280
281 281
@@ -515,6 +515,10 @@ u8 at91_leds_timer;
515 515
516void __init at91_init_leds(u8 cpu_led, u8 timer_led) 516void __init at91_init_leds(u8 cpu_led, u8 timer_led)
517{ 517{
518 /* Enable GPIO to access the LEDs */
519 at91_set_gpio_output(cpu_led, 1);
520 at91_set_gpio_output(timer_led, 1);
521
518 at91_leds_cpu = cpu_led; 522 at91_leds_cpu = cpu_led;
519 at91_leds_timer = timer_led; 523 at91_leds_timer = timer_led;
520} 524}
diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index d242bb885c6d..784d1e682d6d 100644
--- a/arch/arm/mach-at91rm9200/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/mach-at91rm9200/at91sam9261.c 2 * arch/arm/mach-at91/at91sam9261.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * 5 *
@@ -97,6 +97,21 @@ static struct clk spi1_clk = {
97 .pmc_mask = 1 << AT91SAM9261_ID_SPI1, 97 .pmc_mask = 1 << AT91SAM9261_ID_SPI1,
98 .type = CLK_TYPE_PERIPHERAL, 98 .type = CLK_TYPE_PERIPHERAL,
99}; 99};
100static struct clk tc0_clk = {
101 .name = "tc0_clk",
102 .pmc_mask = 1 << AT91SAM9261_ID_TC0,
103 .type = CLK_TYPE_PERIPHERAL,
104};
105static struct clk tc1_clk = {
106 .name = "tc1_clk",
107 .pmc_mask = 1 << AT91SAM9261_ID_TC1,
108 .type = CLK_TYPE_PERIPHERAL,
109};
110static struct clk tc2_clk = {
111 .name = "tc2_clk",
112 .pmc_mask = 1 << AT91SAM9261_ID_TC2,
113 .type = CLK_TYPE_PERIPHERAL,
114};
100static struct clk ohci_clk = { 115static struct clk ohci_clk = {
101 .name = "ohci_clk", 116 .name = "ohci_clk",
102 .pmc_mask = 1 << AT91SAM9261_ID_UHP, 117 .pmc_mask = 1 << AT91SAM9261_ID_UHP,
@@ -121,7 +136,9 @@ static struct clk *periph_clocks[] __initdata = {
121 &spi0_clk, 136 &spi0_clk,
122 &spi1_clk, 137 &spi1_clk,
123 // ssc 0 .. ssc2 138 // ssc 0 .. ssc2
124 // tc0 .. tc2 139 &tc0_clk,
140 &tc1_clk,
141 &tc2_clk,
125 &ohci_clk, 142 &ohci_clk,
126 &lcdc_clk, 143 &lcdc_clk,
127 // irq0 .. irq2 144 // irq0 .. irq2
@@ -208,7 +225,7 @@ static struct at91_gpio_bank at91sam9261_gpio[] = {
208 225
209static void at91sam9261_reset(void) 226static void at91sam9261_reset(void)
210{ 227{
211 at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); 228 at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
212} 229}
213 230
214 231
diff --git a/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index ed1d79081b35..e1504766fd64 100644
--- a/arch/arm/mach-at91rm9200/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/mach-at91rm9200/at91sam9261_devices.c 2 * arch/arm/mach-at91/at91sam9261_devices.c
3 * 3 *
4 * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> 4 * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
5 * Copyright (C) 2005 David Brownell 5 * Copyright (C) 2005 David Brownell
@@ -159,7 +159,7 @@ static struct platform_device at91sam9261_mmc_device = {
159 .num_resources = ARRAY_SIZE(mmc_resources), 159 .num_resources = ARRAY_SIZE(mmc_resources),
160}; 160};
161 161
162void __init at91_add_device_mmc(struct at91_mmc_data *data) 162void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
163{ 163{
164 if (!data) 164 if (!data)
165 return; 165 return;
@@ -192,7 +192,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data)
192 platform_device_register(&at91sam9261_mmc_device); 192 platform_device_register(&at91sam9261_mmc_device);
193} 193}
194#else 194#else
195void __init at91_add_device_mmc(struct at91_mmc_data *data) {} 195void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
196#endif 196#endif
197 197
198 198
@@ -513,6 +513,10 @@ u8 at91_leds_timer;
513 513
514void __init at91_init_leds(u8 cpu_led, u8 timer_led) 514void __init at91_init_leds(u8 cpu_led, u8 timer_led)
515{ 515{
516 /* Enable GPIO to access the LEDs */
517 at91_set_gpio_output(cpu_led, 1);
518 at91_set_gpio_output(timer_led, 1);
519
516 at91_leds_cpu = cpu_led; 520 at91_leds_cpu = cpu_led;
517 at91_leds_timer = timer_led; 521 at91_leds_timer = timer_led;
518} 522}
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
new file mode 100644
index 000000000000..6aa342e8f1b1
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -0,0 +1,313 @@
1/*
2 * arch/arm/mach-at91/at91sam9263.c
3 *
4 * Copyright (C) 2007 Atmel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12
13#include <linux/module.h>
14
15#include <asm/mach/arch.h>
16#include <asm/mach/map.h>
17#include <asm/arch/at91sam9263.h>
18#include <asm/arch/at91_pmc.h>
19#include <asm/arch/at91_rstc.h>
20
21#include "generic.h"
22#include "clock.h"
23
24static struct map_desc at91sam9263_io_desc[] __initdata = {
25 {
26 .virtual = AT91_VA_BASE_SYS,
27 .pfn = __phys_to_pfn(AT91_BASE_SYS),
28 .length = SZ_16K,
29 .type = MT_DEVICE,
30 }, {
31 .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE,
32 .pfn = __phys_to_pfn(AT91SAM9263_SRAM0_BASE),
33 .length = AT91SAM9263_SRAM0_SIZE,
34 .type = MT_DEVICE,
35 }, {
36 .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE,
37 .pfn = __phys_to_pfn(AT91SAM9263_SRAM1_BASE),
38 .length = AT91SAM9263_SRAM1_SIZE,
39 .type = MT_DEVICE,
40 },
41};
42
43/* --------------------------------------------------------------------
44 * Clocks
45 * -------------------------------------------------------------------- */
46
47/*
48 * The peripheral clocks.
49 */
50static struct clk pioA_clk = {
51 .name = "pioA_clk",
52 .pmc_mask = 1 << AT91SAM9263_ID_PIOA,
53 .type = CLK_TYPE_PERIPHERAL,
54};
55static struct clk pioB_clk = {
56 .name = "pioB_clk",
57 .pmc_mask = 1 << AT91SAM9263_ID_PIOB,
58 .type = CLK_TYPE_PERIPHERAL,
59};
60static struct clk pioCDE_clk = {
61 .name = "pioCDE_clk",
62 .pmc_mask = 1 << AT91SAM9263_ID_PIOCDE,
63 .type = CLK_TYPE_PERIPHERAL,
64};
65static struct clk usart0_clk = {
66 .name = "usart0_clk",
67 .pmc_mask = 1 << AT91SAM9263_ID_US0,
68 .type = CLK_TYPE_PERIPHERAL,
69};
70static struct clk usart1_clk = {
71 .name = "usart1_clk",
72 .pmc_mask = 1 << AT91SAM9263_ID_US1,
73 .type = CLK_TYPE_PERIPHERAL,
74};
75static struct clk usart2_clk = {
76 .name = "usart2_clk",
77 .pmc_mask = 1 << AT91SAM9263_ID_US2,
78 .type = CLK_TYPE_PERIPHERAL,
79};
80static struct clk mmc0_clk = {
81 .name = "mci0_clk",
82 .pmc_mask = 1 << AT91SAM9263_ID_MCI0,
83 .type = CLK_TYPE_PERIPHERAL,
84};
85static struct clk mmc1_clk = {
86 .name = "mci1_clk",
87 .pmc_mask = 1 << AT91SAM9263_ID_MCI1,
88 .type = CLK_TYPE_PERIPHERAL,
89};
90static struct clk twi_clk = {
91 .name = "twi_clk",
92 .pmc_mask = 1 << AT91SAM9263_ID_TWI,
93 .type = CLK_TYPE_PERIPHERAL,
94};
95static struct clk spi0_clk = {
96 .name = "spi0_clk",
97 .pmc_mask = 1 << AT91SAM9263_ID_SPI0,
98 .type = CLK_TYPE_PERIPHERAL,
99};
100static struct clk spi1_clk = {
101 .name = "spi1_clk",
102 .pmc_mask = 1 << AT91SAM9263_ID_SPI1,
103 .type = CLK_TYPE_PERIPHERAL,
104};
105static struct clk tcb_clk = {
106 .name = "tcb_clk",
107 .pmc_mask = 1 << AT91SAM9263_ID_TCB,
108 .type = CLK_TYPE_PERIPHERAL,
109};
110static struct clk macb_clk = {
111 .name = "macb_clk",
112 .pmc_mask = 1 << AT91SAM9263_ID_EMAC,
113 .type = CLK_TYPE_PERIPHERAL,
114};
115static struct clk udc_clk = {
116 .name = "udc_clk",
117 .pmc_mask = 1 << AT91SAM9263_ID_UDP,
118 .type = CLK_TYPE_PERIPHERAL,
119};
120static struct clk isi_clk = {
121 .name = "isi_clk",
122 .pmc_mask = 1 << AT91SAM9263_ID_ISI,
123 .type = CLK_TYPE_PERIPHERAL,
124};
125static struct clk lcdc_clk = {
126 .name = "lcdc_clk",
127 .pmc_mask = 1 << AT91SAM9263_ID_ISI,
128 .type = CLK_TYPE_PERIPHERAL,
129};
130static struct clk ohci_clk = {
131 .name = "ohci_clk",
132 .pmc_mask = 1 << AT91SAM9263_ID_UHP,
133 .type = CLK_TYPE_PERIPHERAL,
134};
135
136static struct clk *periph_clocks[] __initdata = {
137 &pioA_clk,
138 &pioB_clk,
139 &pioCDE_clk,
140 &usart0_clk,
141 &usart1_clk,
142 &usart2_clk,
143 &mmc0_clk,
144 &mmc1_clk,
145 // can
146 &twi_clk,
147 &spi0_clk,
148 &spi1_clk,
149 // ssc0 .. ssc1
150 // ac97
151 &tcb_clk,
152 // pwmc
153 &macb_clk,
154 // 2dge
155 &udc_clk,
156 &isi_clk,
157 &lcdc_clk,
158 // dma
159 &ohci_clk,
160 // irq0 .. irq1
161};
162
163/*
164 * The four programmable clocks.
165 * You must configure pin multiplexing to bring these signals out.
166 */
167static struct clk pck0 = {
168 .name = "pck0",
169 .pmc_mask = AT91_PMC_PCK0,
170 .type = CLK_TYPE_PROGRAMMABLE,
171 .id = 0,
172};
173static struct clk pck1 = {
174 .name = "pck1",
175 .pmc_mask = AT91_PMC_PCK1,
176 .type = CLK_TYPE_PROGRAMMABLE,
177 .id = 1,
178};
179static struct clk pck2 = {
180 .name = "pck2",
181 .pmc_mask = AT91_PMC_PCK2,
182 .type = CLK_TYPE_PROGRAMMABLE,
183 .id = 2,
184};
185static struct clk pck3 = {
186 .name = "pck3",
187 .pmc_mask = AT91_PMC_PCK3,
188 .type = CLK_TYPE_PROGRAMMABLE,
189 .id = 3,
190};
191
192static void __init at91sam9263_register_clocks(void)
193{
194 int i;
195
196 for (i = 0; i < ARRAY_SIZE(periph_clocks); i++)
197 clk_register(periph_clocks[i]);
198
199 clk_register(&pck0);
200 clk_register(&pck1);
201 clk_register(&pck2);
202 clk_register(&pck3);
203}
204
205/* --------------------------------------------------------------------
206 * GPIO
207 * -------------------------------------------------------------------- */
208
209static struct at91_gpio_bank at91sam9263_gpio[] = {
210 {
211 .id = AT91SAM9263_ID_PIOA,
212 .offset = AT91_PIOA,
213 .clock = &pioA_clk,
214 }, {
215 .id = AT91SAM9263_ID_PIOB,
216 .offset = AT91_PIOB,
217 .clock = &pioB_clk,
218 }, {
219 .id = AT91SAM9263_ID_PIOCDE,
220 .offset = AT91_PIOC,
221 .clock = &pioCDE_clk,
222 }, {
223 .id = AT91SAM9263_ID_PIOCDE,
224 .offset = AT91_PIOD,
225 .clock = &pioCDE_clk,
226 }, {
227 .id = AT91SAM9263_ID_PIOCDE,
228 .offset = AT91_PIOE,
229 .clock = &pioCDE_clk,
230 }
231};
232
233static void at91sam9263_reset(void)
234{
235 at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
236}
237
238
239/* --------------------------------------------------------------------
240 * AT91SAM9263 processor initialization
241 * -------------------------------------------------------------------- */
242
243void __init at91sam9263_initialize(unsigned long main_clock)
244{
245 /* Map peripherals */
246 iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
247
248 at91_arch_reset = at91sam9263_reset;
249 at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
250
251 /* Init clock subsystem */
252 at91_clock_init(main_clock);
253
254 /* Register the processor-specific clocks */
255 at91sam9263_register_clocks();
256
257 /* Register GPIO subsystem */
258 at91_gpio_init(at91sam9263_gpio, 5);
259}
260
261/* --------------------------------------------------------------------
262 * Interrupt initialization
263 * -------------------------------------------------------------------- */
264
265/*
266 * The default interrupt priority levels (0 = lowest, 7 = highest).
267 */
268static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = {
269 7, /* Advanced Interrupt Controller (FIQ) */
270 7, /* System Peripherals */
271 0, /* Parallel IO Controller A */
272 0, /* Parallel IO Controller B */
273 0, /* Parallel IO Controller C, D and E */
274 0,
275 0,
276 6, /* USART 0 */
277 6, /* USART 1 */
278 6, /* USART 2 */
279 0, /* Multimedia Card Interface 0 */
280 0, /* Multimedia Card Interface 1 */
281 4, /* CAN */
282 0, /* Two-Wire Interface */
283 6, /* Serial Peripheral Interface 0 */
284 6, /* Serial Peripheral Interface 1 */
285 5, /* Serial Synchronous Controller 0 */
286 5, /* Serial Synchronous Controller 1 */
287 6, /* AC97 Controller */
288 0, /* Timer Counter 0, 1 and 2 */
289 0, /* Pulse Width Modulation Controller */
290 3, /* Ethernet */
291 0,
292 0, /* 2D Graphic Engine */
293 3, /* USB Device Port */
294 0, /* Image Sensor Interface */
295 3, /* LDC Controller */
296 0, /* DMA Controller */
297 0,
298 3, /* USB Host port */
299 0, /* Advanced Interrupt Controller (IRQ0) */
300 0, /* Advanced Interrupt Controller (IRQ1) */
301};
302
303void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS])
304{
305 if (!priority)
306 priority = at91sam9263_default_irq_priority;
307
308 /* Initialize the AIC interrupt controller */
309 at91_aic_init(priority);
310
311 /* Enable GPIO interrupts */
312 at91_gpio_irq_setup();
313}
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
new file mode 100644
index 000000000000..d9af7ca58bce
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -0,0 +1,818 @@
1/*
2 * arch/arm/mach-at91/at91sam9263_devices.c
3 *
4 * Copyright (C) 2007 Atmel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 */
12#include <asm/mach/arch.h>
13#include <asm/mach/map.h>
14
15#include <linux/platform_device.h>
16
17#include <asm/arch/board.h>
18#include <asm/arch/gpio.h>
19#include <asm/arch/at91sam9263.h>
20#include <asm/arch/at91sam926x_mc.h>
21#include <asm/arch/at91sam9263_matrix.h>
22
23#include "generic.h"
24
25#define SZ_512 0x00000200
26#define SZ_256 0x00000100
27#define SZ_16 0x00000010
28
29/* --------------------------------------------------------------------
30 * USB Host
31 * -------------------------------------------------------------------- */
32
33#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
34static u64 ohci_dmamask = 0xffffffffUL;
35static struct at91_usbh_data usbh_data;
36
37static struct resource usbh_resources[] = {
38 [0] = {
39 .start = AT91SAM9263_UHP_BASE,
40 .end = AT91SAM9263_UHP_BASE + SZ_1M - 1,
41 .flags = IORESOURCE_MEM,
42 },
43 [1] = {
44 .start = AT91SAM9263_ID_UHP,
45 .end = AT91SAM9263_ID_UHP,
46 .flags = IORESOURCE_IRQ,
47 },
48};
49
50static struct platform_device at91_usbh_device = {
51 .name = "at91_ohci",
52 .id = -1,
53 .dev = {
54 .dma_mask = &ohci_dmamask,
55 .coherent_dma_mask = 0xffffffff,
56 .platform_data = &usbh_data,
57 },
58 .resource = usbh_resources,
59 .num_resources = ARRAY_SIZE(usbh_resources),
60};
61
62void __init at91_add_device_usbh(struct at91_usbh_data *data)
63{
64 int i;
65
66 if (!data)
67 return;
68
69 /* Enable VBus control for UHP ports */
70 for (i = 0; i < data->ports; i++) {
71 if (data->vbus_pin[i])
72 at91_set_gpio_output(data->vbus_pin[i], 0);
73 }
74
75 usbh_data = *data;
76 platform_device_register(&at91_usbh_device);
77}
78#else
79void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
80#endif
81
82
83/* --------------------------------------------------------------------
84 * USB Device (Gadget)
85 * -------------------------------------------------------------------- */
86
87#ifdef CONFIG_USB_GADGET_AT91
88static struct at91_udc_data udc_data;
89
90static struct resource udc_resources[] = {
91 [0] = {
92 .start = AT91SAM9263_BASE_UDP,
93 .end = AT91SAM9263_BASE_UDP + SZ_16K - 1,
94 .flags = IORESOURCE_MEM,
95 },
96 [1] = {
97 .start = AT91SAM9263_ID_UDP,
98 .end = AT91SAM9263_ID_UDP,
99 .flags = IORESOURCE_IRQ,
100 },
101};
102
103static struct platform_device at91_udc_device = {
104 .name = "at91_udc",
105 .id = -1,
106 .dev = {
107 .platform_data = &udc_data,
108 },
109 .resource = udc_resources,
110 .num_resources = ARRAY_SIZE(udc_resources),
111};
112
113void __init at91_add_device_udc(struct at91_udc_data *data)
114{
115 if (!data)
116 return;
117
118 if (data->vbus_pin) {
119 at91_set_gpio_input(data->vbus_pin, 0);
120 at91_set_deglitch(data->vbus_pin, 1);
121 }
122
123 /* Pullup pin is handled internally by USB device peripheral */
124
125 udc_data = *data;
126 platform_device_register(&at91_udc_device);
127}
128#else
129void __init at91_add_device_udc(struct at91_udc_data *data) {}
130#endif
131
132
133/* --------------------------------------------------------------------
134 * Ethernet
135 * -------------------------------------------------------------------- */
136
137#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE)
138static u64 eth_dmamask = 0xffffffffUL;
139static struct at91_eth_data eth_data;
140
141static struct resource eth_resources[] = {
142 [0] = {
143 .start = AT91SAM9263_BASE_EMAC,
144 .end = AT91SAM9263_BASE_EMAC + SZ_16K - 1,
145 .flags = IORESOURCE_MEM,
146 },
147 [1] = {
148 .start = AT91SAM9263_ID_EMAC,
149 .end = AT91SAM9263_ID_EMAC,
150 .flags = IORESOURCE_IRQ,
151 },
152};
153
154static struct platform_device at91sam9263_eth_device = {
155 .name = "macb",
156 .id = -1,
157 .dev = {
158 .dma_mask = &eth_dmamask,
159 .coherent_dma_mask = 0xffffffff,
160 .platform_data = &eth_data,
161 },
162 .resource = eth_resources,
163 .num_resources = ARRAY_SIZE(eth_resources),
164};
165
166void __init at91_add_device_eth(struct at91_eth_data *data)
167{
168 if (!data)
169 return;
170
171 if (data->phy_irq_pin) {
172 at91_set_gpio_input(data->phy_irq_pin, 0);
173 at91_set_deglitch(data->phy_irq_pin, 1);
174 }
175
176 /* Pins used for MII and RMII */
177 at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */
178 at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */
179 at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */
180 at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */
181 at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */
182 at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */
183 at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */
184 at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */
185 at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */
186 at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */
187
188 if (!data->is_rmii) {
189 at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */
190 at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */
191 at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */
192 at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */
193 at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */
194 at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */
195 at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */
196 at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */
197 }
198
199 eth_data = *data;
200 platform_device_register(&at91sam9263_eth_device);
201}
202#else
203void __init at91_add_device_eth(struct at91_eth_data *data) {}
204#endif
205
206
207/* --------------------------------------------------------------------
208 * MMC / SD
209 * -------------------------------------------------------------------- */
210
211#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
212static u64 mmc_dmamask = 0xffffffffUL;
213static struct at91_mmc_data mmc0_data, mmc1_data;
214
215static struct resource mmc0_resources[] = {
216 [0] = {
217 .start = AT91SAM9263_BASE_MCI0,
218 .end = AT91SAM9263_BASE_MCI0 + SZ_16K - 1,
219 .flags = IORESOURCE_MEM,
220 },
221 [1] = {
222 .start = AT91SAM9263_ID_MCI0,
223 .end = AT91SAM9263_ID_MCI0,
224 .flags = IORESOURCE_IRQ,
225 },
226};
227
228static struct platform_device at91sam9263_mmc0_device = {
229 .name = "at91_mci",
230 .id = 0,
231 .dev = {
232 .dma_mask = &mmc_dmamask,
233 .coherent_dma_mask = 0xffffffff,
234 .platform_data = &mmc0_data,
235 },
236 .resource = mmc0_resources,
237 .num_resources = ARRAY_SIZE(mmc0_resources),
238};
239
240static struct resource mmc1_resources[] = {
241 [0] = {
242 .start = AT91SAM9263_BASE_MCI1,
243 .end = AT91SAM9263_BASE_MCI1 + SZ_16K - 1,
244 .flags = IORESOURCE_MEM,
245 },
246 [1] = {
247 .start = AT91SAM9263_ID_MCI1,
248 .end = AT91SAM9263_ID_MCI1,
249 .flags = IORESOURCE_IRQ,
250 },
251};
252
253static struct platform_device at91sam9263_mmc1_device = {
254 .name = "at91_mci",
255 .id = 1,
256 .dev = {
257 .dma_mask = &mmc_dmamask,
258 .coherent_dma_mask = 0xffffffff,
259 .platform_data = &mmc1_data,
260 },
261 .resource = mmc1_resources,
262 .num_resources = ARRAY_SIZE(mmc1_resources),
263};
264
265void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
266{
267 if (!data)
268 return;
269
270 /* input/irq */
271 if (data->det_pin) {
272 at91_set_gpio_input(data->det_pin, 1);
273 at91_set_deglitch(data->det_pin, 1);
274 }
275 if (data->wp_pin)
276 at91_set_gpio_input(data->wp_pin, 1);
277 if (data->vcc_pin)
278 at91_set_gpio_output(data->vcc_pin, 0);
279
280 if (mmc_id == 0) { /* MCI0 */
281 /* CLK */
282 at91_set_A_periph(AT91_PIN_PA12, 0);
283
284 if (data->slot_b) {
285 /* CMD */
286 at91_set_A_periph(AT91_PIN_PA16, 1);
287
288 /* DAT0, maybe DAT1..DAT3 */
289 at91_set_A_periph(AT91_PIN_PA17, 1);
290 if (data->wire4) {
291 at91_set_A_periph(AT91_PIN_PA18, 1);
292 at91_set_A_periph(AT91_PIN_PA19, 1);
293 at91_set_A_periph(AT91_PIN_PA20, 1);
294 }
295 } else {
296 /* CMD */
297 at91_set_A_periph(AT91_PIN_PA1, 1);
298
299 /* DAT0, maybe DAT1..DAT3 */
300 at91_set_A_periph(AT91_PIN_PA0, 1);
301 if (data->wire4) {
302 at91_set_A_periph(AT91_PIN_PA3, 1);
303 at91_set_A_periph(AT91_PIN_PA4, 1);
304 at91_set_A_periph(AT91_PIN_PA5, 1);
305 }
306 }
307
308 mmc0_data = *data;
309 at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
310 platform_device_register(&at91sam9263_mmc0_device);
311 } else { /* MCI1 */
312 /* CLK */
313 at91_set_A_periph(AT91_PIN_PA6, 0);
314
315 if (data->slot_b) {
316 /* CMD */
317 at91_set_A_periph(AT91_PIN_PA21, 1);
318
319 /* DAT0, maybe DAT1..DAT3 */
320 at91_set_A_periph(AT91_PIN_PA22, 1);
321 if (data->wire4) {
322 at91_set_A_periph(AT91_PIN_PA23, 1);
323 at91_set_A_periph(AT91_PIN_PA24, 1);
324 at91_set_A_periph(AT91_PIN_PA25, 1);
325 }
326 } else {
327 /* CMD */
328 at91_set_A_periph(AT91_PIN_PA7, 1);
329
330 /* DAT0, maybe DAT1..DAT3 */
331 at91_set_A_periph(AT91_PIN_PA8, 1);
332 if (data->wire4) {
333 at91_set_A_periph(AT91_PIN_PA9, 1);
334 at91_set_A_periph(AT91_PIN_PA10, 1);
335 at91_set_A_periph(AT91_PIN_PA11, 1);
336 }
337 }
338
339 mmc1_data = *data;
340 at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk");
341 platform_device_register(&at91sam9263_mmc1_device);
342 }
343}
344#else
345void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
346#endif
347
348
349/* --------------------------------------------------------------------
350 * NAND / SmartMedia
351 * -------------------------------------------------------------------- */
352
353#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE)
354static struct at91_nand_data nand_data;
355
356#define NAND_BASE AT91_CHIPSELECT_3
357
358static struct resource nand_resources[] = {
359 {
360 .start = NAND_BASE,
361 .end = NAND_BASE + SZ_256M - 1,
362 .flags = IORESOURCE_MEM,
363 }
364};
365
366static struct platform_device at91sam9263_nand_device = {
367 .name = "at91_nand",
368 .id = -1,
369 .dev = {
370 .platform_data = &nand_data,
371 },
372 .resource = nand_resources,
373 .num_resources = ARRAY_SIZE(nand_resources),
374};
375
376void __init at91_add_device_nand(struct at91_nand_data *data)
377{
378 unsigned long csa, mode;
379
380 if (!data)
381 return;
382
383 csa = at91_sys_read(AT91_MATRIX_EBI0CSA);
384 at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC);
385
386 /* set the bus interface characteristics */
387 at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0)
388 | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0));
389
390 at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3)
391 | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3));
392
393 at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5));
394
395 if (data->bus_width_16)
396 mode = AT91_SMC_DBW_16;
397 else
398 mode = AT91_SMC_DBW_8;
399 at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2));
400
401 /* enable pin */
402 if (data->enable_pin)
403 at91_set_gpio_output(data->enable_pin, 1);
404
405 /* ready/busy pin */
406 if (data->rdy_pin)
407 at91_set_gpio_input(data->rdy_pin, 1);
408
409 /* card detect pin */
410 if (data->det_pin)
411 at91_set_gpio_input(data->det_pin, 1);
412
413 nand_data = *data;
414 platform_device_register(&at91sam9263_nand_device);
415}
416#else
417void __init at91_add_device_nand(struct at91_nand_data *data) {}
418#endif
419
420
421/* --------------------------------------------------------------------
422 * TWI (i2c)
423 * -------------------------------------------------------------------- */
424
425#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE)
426
427static struct resource twi_resources[] = {
428 [0] = {
429 .start = AT91SAM9263_BASE_TWI,
430 .end = AT91SAM9263_BASE_TWI + SZ_16K - 1,
431 .flags = IORESOURCE_MEM,
432 },
433 [1] = {
434 .start = AT91SAM9263_ID_TWI,
435 .end = AT91SAM9263_ID_TWI,
436 .flags = IORESOURCE_IRQ,
437 },
438};
439
440static struct platform_device at91sam9263_twi_device = {
441 .name = "at91_i2c",
442 .id = -1,
443 .resource = twi_resources,
444 .num_resources = ARRAY_SIZE(twi_resources),
445};
446
447void __init at91_add_device_i2c(void)
448{
449 /* pins used for TWI interface */
450 at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */
451 at91_set_multi_drive(AT91_PIN_PB4, 1);
452
453 at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */
454 at91_set_multi_drive(AT91_PIN_PB5, 1);
455
456 platform_device_register(&at91sam9263_twi_device);
457}
458#else
459void __init at91_add_device_i2c(void) {}
460#endif
461
462
463/* --------------------------------------------------------------------
464 * SPI
465 * -------------------------------------------------------------------- */
466
467#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
468static u64 spi_dmamask = 0xffffffffUL;
469
470static struct resource spi0_resources[] = {
471 [0] = {
472 .start = AT91SAM9263_BASE_SPI0,
473 .end = AT91SAM9263_BASE_SPI0 + SZ_16K - 1,
474 .flags = IORESOURCE_MEM,
475 },
476 [1] = {
477 .start = AT91SAM9263_ID_SPI0,
478 .end = AT91SAM9263_ID_SPI0,
479 .flags = IORESOURCE_IRQ,
480 },
481};
482
483static struct platform_device at91sam9263_spi0_device = {
484 .name = "atmel_spi",
485 .id = 0,
486 .dev = {
487 .dma_mask = &spi_dmamask,
488 .coherent_dma_mask = 0xffffffff,
489 },
490 .resource = spi0_resources,
491 .num_resources = ARRAY_SIZE(spi0_resources),
492};
493
494static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 };
495
496static struct resource spi1_resources[] = {
497 [0] = {
498 .start = AT91SAM9263_BASE_SPI1,
499 .end = AT91SAM9263_BASE_SPI1 + SZ_16K - 1,
500 .flags = IORESOURCE_MEM,
501 },
502 [1] = {
503 .start = AT91SAM9263_ID_SPI1,
504 .end = AT91SAM9263_ID_SPI1,
505 .flags = IORESOURCE_IRQ,
506 },
507};
508
509static struct platform_device at91sam9263_spi1_device = {
510 .name = "atmel_spi",
511 .id = 1,
512 .dev = {
513 .dma_mask = &spi_dmamask,
514 .coherent_dma_mask = 0xffffffff,
515 },
516 .resource = spi1_resources,
517 .num_resources = ARRAY_SIZE(spi1_resources),
518};
519
520static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 };
521
522void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
523{
524 int i;
525 unsigned long cs_pin;
526 short enable_spi0 = 0;
527 short enable_spi1 = 0;
528
529 /* Choose SPI chip-selects */
530 for (i = 0; i < nr_devices; i++) {
531 if (devices[i].controller_data)
532 cs_pin = (unsigned long) devices[i].controller_data;
533 else if (devices[i].bus_num == 0)
534 cs_pin = spi0_standard_cs[devices[i].chip_select];
535 else
536 cs_pin = spi1_standard_cs[devices[i].chip_select];
537
538 if (devices[i].bus_num == 0)
539 enable_spi0 = 1;
540 else
541 enable_spi1 = 1;
542
543 /* enable chip-select pin */
544 at91_set_gpio_output(cs_pin, 1);
545
546 /* pass chip-select pin to driver */
547 devices[i].controller_data = (void *) cs_pin;
548 }
549
550 spi_register_board_info(devices, nr_devices);
551
552 /* Configure SPI bus(es) */
553 if (enable_spi0) {
554 at91_set_B_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */
555 at91_set_B_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */
556 at91_set_B_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */
557
558 at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk");
559 platform_device_register(&at91sam9263_spi0_device);
560 }
561 if (enable_spi1) {
562 at91_set_A_periph(AT91_PIN_PB12, 0); /* SPI1_MISO */
563 at91_set_A_periph(AT91_PIN_PB13, 0); /* SPI1_MOSI */
564 at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_SPCK */
565
566 at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk");
567 platform_device_register(&at91sam9263_spi1_device);
568 }
569}
570#else
571void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
572#endif
573
574
575/* --------------------------------------------------------------------
576 * LEDs
577 * -------------------------------------------------------------------- */
578
579#if defined(CONFIG_LEDS)
580u8 at91_leds_cpu;
581u8 at91_leds_timer;
582
583void __init at91_init_leds(u8 cpu_led, u8 timer_led)
584{
585 /* Enable GPIO to access the LEDs */
586 at91_set_gpio_output(cpu_led, 1);
587 at91_set_gpio_output(timer_led, 1);
588
589 at91_leds_cpu = cpu_led;
590 at91_leds_timer = timer_led;
591}
592#else
593void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
594#endif
595
596
597/* --------------------------------------------------------------------
598 * UART
599 * -------------------------------------------------------------------- */
600
601#if defined(CONFIG_SERIAL_ATMEL)
602
603static struct resource dbgu_resources[] = {
604 [0] = {
605 .start = AT91_VA_BASE_SYS + AT91_DBGU,
606 .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
607 .flags = IORESOURCE_MEM,
608 },
609 [1] = {
610 .start = AT91_ID_SYS,
611 .end = AT91_ID_SYS,
612 .flags = IORESOURCE_IRQ,
613 },
614};
615
616static struct atmel_uart_data dbgu_data = {
617 .use_dma_tx = 0,
618 .use_dma_rx = 0, /* DBGU not capable of receive DMA */
619 .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
620};
621
622static struct platform_device at91sam9263_dbgu_device = {
623 .name = "atmel_usart",
624 .id = 0,
625 .dev = {
626 .platform_data = &dbgu_data,
627 .coherent_dma_mask = 0xffffffff,
628 },
629 .resource = dbgu_resources,
630 .num_resources = ARRAY_SIZE(dbgu_resources),
631};
632
633static inline void configure_dbgu_pins(void)
634{
635 at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */
636 at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */
637}
638
639static struct resource uart0_resources[] = {
640 [0] = {
641 .start = AT91SAM9263_BASE_US0,
642 .end = AT91SAM9263_BASE_US0 + SZ_16K - 1,
643 .flags = IORESOURCE_MEM,
644 },
645 [1] = {
646 .start = AT91SAM9263_ID_US0,
647 .end = AT91SAM9263_ID_US0,
648 .flags = IORESOURCE_IRQ,
649 },
650};
651
652static struct atmel_uart_data uart0_data = {
653 .use_dma_tx = 1,
654 .use_dma_rx = 1,
655};
656
657static struct platform_device at91sam9263_uart0_device = {
658 .name = "atmel_usart",
659 .id = 1,
660 .dev = {
661 .platform_data = &uart0_data,
662 .coherent_dma_mask = 0xffffffff,
663 },
664 .resource = uart0_resources,
665 .num_resources = ARRAY_SIZE(uart0_resources),
666};
667
668static inline void configure_usart0_pins(void)
669{
670 at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */
671 at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */
672 at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */
673 at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */
674}
675
676static struct resource uart1_resources[] = {
677 [0] = {
678 .start = AT91SAM9263_BASE_US1,
679 .end = AT91SAM9263_BASE_US1 + SZ_16K - 1,
680 .flags = IORESOURCE_MEM,
681 },
682 [1] = {
683 .start = AT91SAM9263_ID_US1,
684 .end = AT91SAM9263_ID_US1,
685 .flags = IORESOURCE_IRQ,
686 },
687};
688
689static struct atmel_uart_data uart1_data = {
690 .use_dma_tx = 1,
691 .use_dma_rx = 1,
692};
693
694static struct platform_device at91sam9263_uart1_device = {
695 .name = "atmel_usart",
696 .id = 2,
697 .dev = {
698 .platform_data = &uart1_data,
699 .coherent_dma_mask = 0xffffffff,
700 },
701 .resource = uart1_resources,
702 .num_resources = ARRAY_SIZE(uart1_resources),
703};
704
705static inline void configure_usart1_pins(void)
706{
707 at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */
708 at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */
709 at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */
710 at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */
711}
712
713static struct resource uart2_resources[] = {
714 [0] = {
715 .start = AT91SAM9263_BASE_US2,
716 .end = AT91SAM9263_BASE_US2 + SZ_16K - 1,
717 .flags = IORESOURCE_MEM,
718 },
719 [1] = {
720 .start = AT91SAM9263_ID_US2,
721 .end = AT91SAM9263_ID_US2,
722 .flags = IORESOURCE_IRQ,
723 },
724};
725
726static struct atmel_uart_data uart2_data = {
727 .use_dma_tx = 1,
728 .use_dma_rx = 1,
729};
730
731static struct platform_device at91sam9263_uart2_device = {
732 .name = "atmel_usart",
733 .id = 3,
734 .dev = {
735 .platform_data = &uart2_data,
736 .coherent_dma_mask = 0xffffffff,
737 },
738 .resource = uart2_resources,
739 .num_resources = ARRAY_SIZE(uart2_resources),
740};
741
742static inline void configure_usart2_pins(void)
743{
744 at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */
745 at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */
746 at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */
747 at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */
748}
749
750struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */
751struct platform_device *atmel_default_console_device; /* the serial console device */
752
753void __init at91_init_serial(struct at91_uart_config *config)
754{
755 int i;
756
757 /* Fill in list of supported UARTs */
758 for (i = 0; i < config->nr_tty; i++) {
759 switch (config->tty_map[i]) {
760 case 0:
761 configure_usart0_pins();
762 at91_uarts[i] = &at91sam9263_uart0_device;
763 at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart");
764 break;
765 case 1:
766 configure_usart1_pins();
767 at91_uarts[i] = &at91sam9263_uart1_device;
768 at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart");
769 break;
770 case 2:
771 configure_usart2_pins();
772 at91_uarts[i] = &at91sam9263_uart2_device;
773 at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart");
774 break;
775 case 3:
776 configure_dbgu_pins();
777 at91_uarts[i] = &at91sam9263_dbgu_device;
778 at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart");
779 break;
780 default:
781 continue;
782 }
783 at91_uarts[i]->id = i; /* update ID number to mapped ID */
784 }
785
786 /* Set serial console device */
787 if (config->console_tty < ATMEL_MAX_UART)
788 atmel_default_console_device = at91_uarts[config->console_tty];
789 if (!atmel_default_console_device)
790 printk(KERN_INFO "AT91: No default serial console defined.\n");
791}
792
793void __init at91_add_device_serial(void)
794{
795 int i;
796
797 for (i = 0; i < ATMEL_MAX_UART; i++) {
798 if (at91_uarts[i])
799 platform_device_register(at91_uarts[i]);
800 }
801}
802#else
803void __init at91_init_serial(struct at91_uart_config *config) {}
804void __init at91_add_device_serial(void) {}
805#endif
806
807
808/* -------------------------------------------------------------------- */
809/*
810 * These devices are always present and don't need any board-specific
811 * setup.
812 */
813static int __init at91_add_standard_devices(void)
814{
815 return 0;
816}
817
818arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 99df5f6ee42e..a4dded27fa16 100644
--- a/arch/arm/mach-at91rm9200/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c 2 * linux/arch/arm/mach-at91/at91sam926x_time.c
3 * 3 *
4 * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France 4 * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France
5 * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France 5 * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France
@@ -30,7 +30,6 @@
30 * Returns number of microseconds since last timer interrupt. Note that interrupts 30 * Returns number of microseconds since last timer interrupt. Note that interrupts
31 * will have been disabled by do_gettimeofday() 31 * will have been disabled by do_gettimeofday()
32 * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. 32 * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy.
33 * 'tick' is usecs per jiffy (linux/timex.h).
34 */ 33 */
35static unsigned long at91sam926x_gettimeoffset(void) 34static unsigned long at91sam926x_gettimeoffset(void)
36{ 35{
@@ -39,7 +38,7 @@ static unsigned long at91sam926x_gettimeoffset(void)
39 38
40 elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */ 39 elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */
41 40
42 return (unsigned long)(elapsed * 1000000) / LATCH; 41 return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH;
43} 42}
44 43
45/* 44/*
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index 971c3e2d8e36..2d3d4b6f7b02 100644
--- a/arch/arm/mach-at91rm9200/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-1arm.c 2 * linux/arch/arm/mach-at91/board-1arm.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * 5 *
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index 654f0379550a..b4518619063a 100644
--- a/arch/arm/mach-at91rm9200/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-carmeva.c 2 * linux/arch/arm/mach-at91/board-carmeva.c
3 * 3 *
4 * Copyright (c) 2005 Peer Georgi 4 * Copyright (c) 2005 Peer Georgi
5 * Conitec Datasystems 5 * Conitec Datasystems
@@ -134,7 +134,7 @@ static void __init carmeva_board_init(void)
134 /* Compact Flash */ 134 /* Compact Flash */
135// at91_add_device_cf(&carmeva_cf_data); 135// at91_add_device_cf(&carmeva_cf_data);
136 /* MMC */ 136 /* MMC */
137 at91_add_device_mmc(&carmeva_mmc_data); 137 at91_add_device_mmc(0, &carmeva_mmc_data);
138} 138}
139 139
140MACHINE_START(CARMEVA, "Carmeva") 140MACHINE_START(CARMEVA, "Carmeva")
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index b8bb8052607a..e18a41e61f0c 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-csb337.c 2 * linux/arch/arm/mach-at91/board-csb337.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * 5 *
@@ -24,6 +24,7 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/spi/spi.h> 26#include <linux/spi/spi.h>
27#include <linux/mtd/physmap.h>
27 28
28#include <asm/hardware.h> 29#include <asm/hardware.h>
29#include <asm/setup.h> 30#include <asm/setup.h>
@@ -112,6 +113,42 @@ static struct spi_board_info csb337_spi_devices[] = {
112 }, 113 },
113}; 114};
114 115
116#define CSB_FLASH_BASE AT91_CHIPSELECT_0
117#define CSB_FLASH_SIZE 0x800000
118
119static struct mtd_partition csb_flash_partitions[] = {
120 {
121 .name = "uMON flash",
122 .offset = 0,
123 .size = MTDPART_SIZ_FULL,
124 .mask_flags = MTD_WRITEABLE, /* read only */
125 }
126};
127
128static struct physmap_flash_data csb_flash_data = {
129 .width = 2,
130 .parts = csb_flash_partitions,
131 .nr_parts = ARRAY_SIZE(csb_flash_partitions),
132};
133
134static struct resource csb_flash_resources[] = {
135 {
136 .start = CSB_FLASH_BASE,
137 .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
138 .flags = IORESOURCE_MEM,
139 }
140};
141
142static struct platform_device csb_flash = {
143 .name = "physmap-flash",
144 .id = 0,
145 .dev = {
146 .platform_data = &csb_flash_data,
147 },
148 .resource = csb_flash_resources,
149 .num_resources = ARRAY_SIZE(csb_flash_resources),
150};
151
115static void __init csb337_board_init(void) 152static void __init csb337_board_init(void)
116{ 153{
117 /* Serial */ 154 /* Serial */
@@ -130,7 +167,9 @@ static void __init csb337_board_init(void)
130 /* SPI */ 167 /* SPI */
131 at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); 168 at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
132 /* MMC */ 169 /* MMC */
133 at91_add_device_mmc(&csb337_mmc_data); 170 at91_add_device_mmc(0, &csb337_mmc_data);
171 /* NOR flash */
172 platform_device_register(&csb_flash);
134} 173}
135 174
136MACHINE_START(CSB337, "Cogent CSB337") 175MACHINE_START(CSB337, "Cogent CSB337")
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index a29fa0e822ce..77f04b935b3a 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-csb637.c 2 * linux/arch/arm/mach-at91/board-csb637.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * 5 *
@@ -23,6 +23,7 @@
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#include <linux/mtd/physmap.h>
26 27
27#include <asm/hardware.h> 28#include <asm/hardware.h>
28#include <asm/setup.h> 29#include <asm/setup.h>
@@ -81,6 +82,42 @@ static struct at91_udc_data __initdata csb637_udc_data = {
81 .pullup_pin = AT91_PIN_PB1, 82 .pullup_pin = AT91_PIN_PB1,
82}; 83};
83 84
85#define CSB_FLASH_BASE AT91_CHIPSELECT_0
86#define CSB_FLASH_SIZE 0x1000000
87
88static struct mtd_partition csb_flash_partitions[] = {
89 {
90 .name = "uMON flash",
91 .offset = 0,
92 .size = MTDPART_SIZ_FULL,
93 .mask_flags = MTD_WRITEABLE, /* read only */
94 }
95};
96
97static struct physmap_flash_data csb_flash_data = {
98 .width = 2,
99 .parts = csb_flash_partitions,
100 .nr_parts = ARRAY_SIZE(csb_flash_partitions),
101};
102
103static struct resource csb_flash_resources[] = {
104 {
105 .start = CSB_FLASH_BASE,
106 .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1,
107 .flags = IORESOURCE_MEM,
108 }
109};
110
111static struct platform_device csb_flash = {
112 .name = "physmap-flash",
113 .id = 0,
114 .dev = {
115 .platform_data = &csb_flash_data,
116 },
117 .resource = csb_flash_resources,
118 .num_resources = ARRAY_SIZE(csb_flash_resources),
119};
120
84static void __init csb637_board_init(void) 121static void __init csb637_board_init(void)
85{ 122{
86 /* Serial */ 123 /* Serial */
@@ -95,6 +132,8 @@ static void __init csb637_board_init(void)
95 at91_add_device_i2c(); 132 at91_add_device_i2c();
96 /* SPI */ 133 /* SPI */
97 at91_add_device_spi(NULL, 0); 134 at91_add_device_spi(NULL, 0);
135 /* NOR flash */
136 platform_device_register(&csb_flash);
98} 137}
99 138
100MACHINE_START(CSB637, "Cogent CSB637") 139MACHINE_START(CSB637, "Cogent CSB637")
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91/board-dk.c
index 7522bf91bce8..6043c38c0a9e 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91/board-dk.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-dk.c 2 * linux/arch/arm/mach-at91/board-dk.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * 5 *
@@ -194,7 +194,7 @@ static void __init dk_board_init(void)
194#else 194#else
195 /* MMC */ 195 /* MMC */
196 at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ 196 at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
197 at91_add_device_mmc(&dk_mmc_data); 197 at91_add_device_mmc(0, &dk_mmc_data);
198#endif 198#endif
199 /* NAND */ 199 /* NAND */
200 at91_add_device_nand(&dk_nand_data); 200 at91_add_device_nand(&dk_nand_data);
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 80b72cf7264c..20458b5548f0 100644
--- a/arch/arm/mach-at91rm9200/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-eb9200.c 2 * linux/arch/arm/mach-at91/board-eb9200.c
3 * 3 *
4 * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest 4 * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
5 * by Andrew Patrikalakis 5 * by Andrew Patrikalakis
@@ -109,7 +109,7 @@ static void __init eb9200_board_init(void)
109 at91_add_device_spi(NULL, 0); 109 at91_add_device_spi(NULL, 0);
110 /* MMC */ 110 /* MMC */
111 /* only supports 1 or 4 bit interface, not wired through to SPI */ 111 /* only supports 1 or 4 bit interface, not wired through to SPI */
112 at91_add_device_mmc(&eb9200_mmc_data); 112 at91_add_device_mmc(0, &eb9200_mmc_data);
113} 113}
114 114
115MACHINE_START(ATEB9200, "Embest ATEB9200") 115MACHINE_START(ATEB9200, "Embest ATEB9200")
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91/board-ek.c
index c4fdb415f20e..322fdd75a1e4 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91/board-ek.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-ek.c 2 * linux/arch/arm/mach-at91/board-ek.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * 5 *
@@ -154,7 +154,7 @@ static void __init ek_board_init(void)
154#else 154#else
155 /* MMC */ 155 /* MMC */
156 at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ 156 at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
157 at91_add_device_mmc(&ek_mmc_data); 157 at91_add_device_mmc(0, &ek_mmc_data);
158#endif 158#endif
159 /* NOR Flash */ 159 /* NOR Flash */
160 platform_device_register(&ek_flash); 160 platform_device_register(&ek_flash);
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index 6ef3c4879829..c77d84ce9cae 100644
--- a/arch/arm/mach-at91rm9200/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-kafa.c 2 * linux/arch/arm/mach-at91/board-kafa.c
3 * 3 *
4 * Copyright (C) 2006 Sperry-Sun 4 * Copyright (C) 2006 Sperry-Sun
5 * 5 *
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 759d8191854f..76f6e1e553ea 100644
--- a/arch/arm/mach-at91rm9200/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-kb9202.c 2 * linux/arch/arm/mach-at91/board-kb9202.c
3 * 3 *
4 * Copyright (c) 2005 kb_admin 4 * Copyright (c) 2005 kb_admin
5 * KwikByte, Inc. 5 * KwikByte, Inc.
@@ -122,7 +122,7 @@ static void __init kb9202_board_init(void)
122 /* USB Device */ 122 /* USB Device */
123 at91_add_device_udc(&kb9202_udc_data); 123 at91_add_device_udc(&kb9202_udc_data);
124 /* MMC */ 124 /* MMC */
125 at91_add_device_mmc(&kb9202_mmc_data); 125 at91_add_device_mmc(0, &kb9202_mmc_data);
126 /* I2C */ 126 /* I2C */
127 at91_add_device_i2c(); 127 at91_add_device_i2c();
128 /* SPI */ 128 /* SPI */
diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index da5d58ac870b..57fb4499d969 100644
--- a/arch/arm/mach-at91rm9200/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-ek.c 2 * linux/arch/arm/mach-at91/board-sam9260ek.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2006 Atmel 5 * Copyright (C) 2006 Atmel
@@ -118,7 +118,7 @@ static struct spi_board_info ek_spi_devices[] = {
118/* 118/*
119 * MACB Ethernet device 119 * MACB Ethernet device
120 */ 120 */
121static struct __initdata eth_platform_data ek_macb_data = { 121static struct __initdata at91_eth_data ek_macb_data = {
122 .phy_irq_pin = AT91_PIN_PA7, 122 .phy_irq_pin = AT91_PIN_PA7,
123 .is_rmii = 1, 123 .is_rmii = 1,
124}; 124};
@@ -187,7 +187,7 @@ static void __init ek_board_init(void)
187 /* Ethernet */ 187 /* Ethernet */
188 at91_add_device_eth(&ek_macb_data); 188 at91_add_device_eth(&ek_macb_data);
189 /* MMC */ 189 /* MMC */
190 at91_add_device_mmc(&ek_mmc_data); 190 at91_add_device_mmc(0, &ek_mmc_data);
191} 191}
192 192
193MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") 193MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
diff --git a/arch/arm/mach-at91rm9200/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 30b490d8886b..b7e772467cf6 100644
--- a/arch/arm/mach-at91rm9200/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/board-ek.c 2 * linux/arch/arm/mach-at91/board-sam9261ek.c
3 * 3 *
4 * Copyright (C) 2005 SAN People 4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2006 Atmel 5 * Copyright (C) 2006 Atmel
@@ -243,7 +243,7 @@ static void __init ek_board_init(void)
243 at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); 243 at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
244#else 244#else
245 /* MMC */ 245 /* MMC */
246 at91_add_device_mmc(&ek_mmc_data); 246 at91_add_device_mmc(0, &ek_mmc_data);
247#endif 247#endif
248} 248}
249 249
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
new file mode 100644
index 000000000000..8fdce11a880c
--- /dev/null
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -0,0 +1,176 @@
1/*
2 * linux/arch/arm/mach-at91/board-sam9263ek.c
3 *
4 * Copyright (C) 2005 SAN People
5 * Copyright (C) 2007 Atmel Corporation.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/types.h>
23#include <linux/init.h>
24#include <linux/mm.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/spi/spi.h>
28
29#include <asm/hardware.h>
30#include <asm/setup.h>
31#include <asm/mach-types.h>
32#include <asm/irq.h>
33
34#include <asm/mach/arch.h>
35#include <asm/mach/map.h>
36#include <asm/mach/irq.h>
37
38#include <asm/arch/board.h>
39#include <asm/arch/gpio.h>
40#include <asm/arch/at91sam926x_mc.h>
41
42#include "generic.h"
43
44
45/*
46 * Serial port configuration.
47 * 0 .. 2 = USART0 .. USART2
48 * 3 = DBGU
49 */
50static struct at91_uart_config __initdata ek_uart_config = {
51 .console_tty = 0, /* ttyS0 */
52 .nr_tty = 2,
53 .tty_map = { 3, 0, -1, -1, } /* ttyS0, ..., ttyS3 */
54};
55
56static void __init ek_map_io(void)
57{
58 /* Initialize processor: 16.367 MHz crystal */
59 at91sam9263_initialize(16367660);
60
61 /* Setup the serial ports and console */
62 at91_init_serial(&ek_uart_config);
63}
64
65static void __init ek_init_irq(void)
66{
67 at91sam9263_init_interrupts(NULL);
68}
69
70
71/*
72 * USB Host port
73 */
74static struct at91_usbh_data __initdata ek_usbh_data = {
75 .ports = 2,
76 .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 },
77};
78
79/*
80 * USB Device port
81 */
82static struct at91_udc_data __initdata ek_udc_data = {
83 .vbus_pin = AT91_PIN_PA25,
84 .pullup_pin = 0, /* pull-up driven by UDC */
85};
86
87
88/*
89 * SPI devices.
90 */
91static struct spi_board_info ek_spi_devices[] = {
92#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
93 { /* DataFlash card */
94 .modalias = "mtd_dataflash",
95 .chip_select = 0,
96 .max_speed_hz = 15 * 1000 * 1000,
97 .bus_num = 0,
98 },
99#endif
100};
101
102
103/*
104 * MCI (SD/MMC)
105 */
106static struct at91_mmc_data __initdata ek_mmc_data = {
107 .wire4 = 1,
108 .det_pin = AT91_PIN_PE18,
109 .wp_pin = AT91_PIN_PE19,
110// .vcc_pin = ... not connected
111};
112
113
114/*
115 * NAND flash
116 */
117static struct mtd_partition __initdata ek_nand_partition[] = {
118 {
119 .name = "Partition 1",
120 .offset = 0,
121 .size = 64 * 1024 * 1024,
122 },
123 {
124 .name = "Partition 2",
125 .offset = 64 * 1024 * 1024,
126 .size = MTDPART_SIZ_FULL,
127 },
128};
129
130static struct mtd_partition *nand_partitions(int size, int *num_partitions)
131{
132 *num_partitions = ARRAY_SIZE(ek_nand_partition);
133 return ek_nand_partition;
134}
135
136static struct at91_nand_data __initdata ek_nand_data = {
137 .ale = 21,
138 .cle = 22,
139// .det_pin = ... not connected
140 .rdy_pin = AT91_PIN_PA22,
141 .enable_pin = AT91_PIN_PD15,
142 .partition_info = nand_partitions,
143#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
144 .bus_width_16 = 1,
145#else
146 .bus_width_16 = 0,
147#endif
148};
149
150
151static void __init ek_board_init(void)
152{
153 /* Serial */
154 at91_add_device_serial();
155 /* USB Host */
156 at91_add_device_usbh(&ek_usbh_data);
157 /* USB Device */
158 at91_add_device_udc(&ek_udc_data);
159 /* SPI */
160 at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
161 /* MMC */
162 at91_add_device_mmc(1, &ek_mmc_data);
163 /* NAND */
164 at91_add_device_nand(&ek_nand_data);
165}
166
167MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
168 /* Maintainer: Atmel */
169 .phys_io = AT91_BASE_SYS,
170 .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
171 .boot_params = AT91_SDRAM_BASE + 0x100,
172 .timer = &at91sam926x_timer,
173 .map_io = ek_map_io,
174 .init_irq = ek_init_irq,
175 .init_machine = ek_board_init,
176MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91/clock.c
index 4dee21fefe5a..f6cb74806043 100644
--- a/arch/arm/mach-at91rm9200/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/clock.c 2 * linux/arch/arm/mach-at91/clock.c
3 * 3 *
4 * Copyright (C) 2005 David Brownell 4 * Copyright (C) 2005 David Brownell
5 * Copyright (C) 2005 Ivan Kokshaysky 5 * Copyright (C) 2005 Ivan Kokshaysky
@@ -525,27 +525,6 @@ fail:
525 return 0; 525 return 0;
526} 526}
527 527
528/*
529 * Several unused clocks may be active. Turn them off.
530 */
531static void __init at91_periphclk_reset(void)
532{
533 unsigned long reg;
534 struct clk *clk;
535
536 reg = at91_sys_read(AT91_PMC_PCSR);
537
538 list_for_each_entry(clk, &clocks, node) {
539 if (clk->mode != pmc_periph_mode)
540 continue;
541
542 if (clk->users > 0)
543 reg &= ~clk->pmc_mask;
544 }
545
546 at91_sys_write(AT91_PMC_PCDR, reg);
547}
548
549static struct clk *const standard_pmc_clocks[] __initdata = { 528static struct clk *const standard_pmc_clocks[] __initdata = {
550 /* four primary clocks */ 529 /* four primary clocks */
551 &clk32k, 530 &clk32k,
@@ -586,7 +565,7 @@ int __init at91_clock_init(unsigned long main_clock)
586 pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); 565 pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
587 566
588 /* 567 /*
589 * USB clock init: choose 48 MHz PLLB value, turn all clocks off, 568 * USB clock init: choose 48 MHz PLLB value,
590 * disable 48MHz clock during usb peripheral suspend. 569 * disable 48MHz clock during usb peripheral suspend.
591 * 570 *
592 * REVISIT: assumes MCK doesn't derive from PLLB! 571 * REVISIT: assumes MCK doesn't derive from PLLB!
@@ -596,16 +575,10 @@ int __init at91_clock_init(unsigned long main_clock)
596 if (cpu_is_at91rm9200()) { 575 if (cpu_is_at91rm9200()) {
597 uhpck.pmc_mask = AT91RM9200_PMC_UHP; 576 uhpck.pmc_mask = AT91RM9200_PMC_UHP;
598 udpck.pmc_mask = AT91RM9200_PMC_UDP; 577 udpck.pmc_mask = AT91RM9200_PMC_UDP;
599 at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP);
600 at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); 578 at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
601 } else if (cpu_is_at91sam9260()) { 579 } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
602 uhpck.pmc_mask = AT91SAM926x_PMC_UHP; 580 uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
603 udpck.pmc_mask = AT91SAM926x_PMC_UDP; 581 udpck.pmc_mask = AT91SAM926x_PMC_UDP;
604 at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP);
605 } else if (cpu_is_at91sam9261()) {
606 uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0);
607 udpck.pmc_mask = AT91SAM926x_PMC_UDP;
608 at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP);
609 } 582 }
610 at91_sys_write(AT91_CKGR_PLLBR, 0); 583 at91_sys_write(AT91_CKGR_PLLBR, 0);
611 584
@@ -634,11 +607,34 @@ int __init at91_clock_init(unsigned long main_clock)
634 (unsigned) main_clock / 1000000, 607 (unsigned) main_clock / 1000000,
635 ((unsigned) main_clock % 1000000) / 1000); 608 ((unsigned) main_clock % 1000000) / 1000);
636 609
637 /* disable all programmable clocks */ 610 return 0;
638 at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); 611}
612
613/*
614 * Several unused clocks may be active. Turn them off.
615 */
616static int __init at91_clock_reset(void)
617{
618 unsigned long pcdr = 0;
619 unsigned long scdr = 0;
620 struct clk *clk;
621
622 list_for_each_entry(clk, &clocks, node) {
623 if (clk->users > 0)
624 continue;
625
626 if (clk->mode == pmc_periph_mode)
627 pcdr |= clk->pmc_mask;
628
629 if (clk->mode == pmc_sys_mode)
630 scdr |= clk->pmc_mask;
631
632 pr_debug("Clocks: disable unused %s\n", clk->name);
633 }
639 634
640 /* disable all other unused peripheral clocks */ 635 at91_sys_write(AT91_PMC_PCDR, pcdr);
641 at91_periphclk_reset(); 636 at91_sys_write(AT91_PMC_SCDR, scdr);
642 637
643 return 0; 638 return 0;
644} 639}
640late_initcall(at91_clock_reset);
diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91/clock.h
index b5c7a2eb2d1d..1ba3b95ff359 100644
--- a/arch/arm/mach-at91rm9200/clock.h
+++ b/arch/arm/mach-at91/clock.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/clock.h 2 * linux/arch/arm/mach-at91/clock.h
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91/generic.h
index 8c4d5a77d485..bda26221c522 100644
--- a/arch/arm/mach-at91rm9200/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/generic.h 2 * linux/arch/arm/mach-at91/generic.h
3 * 3 *
4 * Copyright (C) 2005 David Brownell 4 * Copyright (C) 2005 David Brownell
5 * 5 *
@@ -12,11 +12,13 @@
12extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); 12extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks);
13extern void __init at91sam9260_initialize(unsigned long main_clock); 13extern void __init at91sam9260_initialize(unsigned long main_clock);
14extern void __init at91sam9261_initialize(unsigned long main_clock); 14extern void __init at91sam9261_initialize(unsigned long main_clock);
15extern void __init at91sam9263_initialize(unsigned long main_clock);
15 16
16 /* Interrupts */ 17 /* Interrupts */
17extern void __init at91rm9200_init_interrupts(unsigned int priority[]); 18extern void __init at91rm9200_init_interrupts(unsigned int priority[]);
18extern void __init at91sam9260_init_interrupts(unsigned int priority[]); 19extern void __init at91sam9260_init_interrupts(unsigned int priority[]);
19extern void __init at91sam9261_init_interrupts(unsigned int priority[]); 20extern void __init at91sam9261_init_interrupts(unsigned int priority[]);
21extern void __init at91sam9263_init_interrupts(unsigned int priority[]);
20extern void __init at91_aic_init(unsigned int priority[]); 22extern void __init at91_aic_init(unsigned int priority[]);
21 23
22 /* Timer */ 24 /* Timer */
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91/gpio.c
index af22659c8a28..9b7495cd555d 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/gpio.c 2 * linux/arch/arm/mach-at91/gpio.c
3 * 3 *
4 * Copyright (C) 2005 HP Labs 4 * Copyright (C) 2005 HP Labs
5 * 5 *
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91/irq.c
index 2148daafd29c..78a5cdb746dc 100644
--- a/arch/arm/mach-at91rm9200/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/arm/mach-at91rm9200/irq.c 2 * linux/arch/arm/mach-at91/irq.c
3 * 3 *
4 * Copyright (C) 2004 SAN People 4 * Copyright (C) 2004 SAN People
5 * Copyright (C) 2004 ATMEL 5 * Copyright (C) 2004 ATMEL
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91/leds.c
index 1a333730466e..0d5144973988 100644
--- a/arch/arm/mach-at91rm9200/leds.c
+++ b/arch/arm/mach-at91/leds.c
@@ -86,10 +86,6 @@ static int __init leds_init(void)
86 if (!at91_leds_timer || !at91_leds_cpu) 86 if (!at91_leds_timer || !at91_leds_cpu)
87 return -ENODEV; 87 return -ENODEV;
88 88
89 /* Enable PIO to access the LEDs */
90 at91_set_gpio_output(at91_leds_timer, 1);
91 at91_set_gpio_output(at91_leds_cpu, 1);
92
93 leds_event = at91_leds_event; 89 leds_event = at91_leds_event;
94 90
95 leds_event(led_start); 91 leds_event(led_start);
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91/pm.c
index 67aa5572a3ea..b49bfda53d7f 100644
--- a/arch/arm/mach-at91rm9200/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * arch/arm/mach-at91rm9200/pm.c 2 * arch/arm/mach-at91/pm.c
3 * AT91 Power Management 3 * AT91 Power Management
4 * 4 *
5 * Copyright (C) 2005 David Brownell 5 * Copyright (C) 2005 David Brownell
@@ -80,6 +80,8 @@ static int at91_pm_verify_clocks(void)
80#warning "Check SAM9260 USB clocks" 80#warning "Check SAM9260 USB clocks"
81 } else if (cpu_is_at91sam9261()) { 81 } else if (cpu_is_at91sam9261()) {
82#warning "Check SAM9261 USB clocks" 82#warning "Check SAM9261 USB clocks"
83 } else if (cpu_is_at91sam9263()) {
84#warning "Check SAM9263 USB clocks"
83 } 85 }
84 86
85#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS 87#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index 08ad782c1649..f174d1a3b11c 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -13,6 +13,7 @@
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/clk.h> 14#include <linux/clk.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/module.h>
16#include <linux/string.h> 17#include <linux/string.h>
17#include <asm/div64.h> 18#include <asm/div64.h>
18#include <asm/hardware.h> 19#include <asm/hardware.h>
@@ -124,7 +125,7 @@ static unsigned long calc_pll_rate(u32 config_word)
124 return (unsigned long)rate; 125 return (unsigned long)rate;
125} 126}
126 127
127void ep93xx_clock_init(void) 128static int __init ep93xx_clock_init(void)
128{ 129{
129 u32 value; 130 u32 value;
130 131
@@ -153,4 +154,7 @@ void ep93xx_clock_init(void)
153 printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", 154 printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
154 clk_f.rate / 1000000, clk_h.rate / 1000000, 155 clk_f.rate / 1000000, clk_h.rate / 1000000,
155 clk_p.rate / 1000000); 156 clk_p.rate / 1000000);
157
158 return 0;
156} 159}
160arch_initcall(ep93xx_clock_init);
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 6b26346191c0..829aed696d98 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -152,22 +152,30 @@ struct sys_timer ep93xx_timer = {
152/************************************************************************* 152/*************************************************************************
153 * GPIO handling for EP93xx 153 * GPIO handling for EP93xx
154 *************************************************************************/ 154 *************************************************************************/
155static unsigned char gpio_int_enable[2]; 155static unsigned char gpio_int_unmasked[3];
156static unsigned char gpio_int_type1[2]; 156static unsigned char gpio_int_enabled[3];
157static unsigned char gpio_int_type2[2]; 157static unsigned char gpio_int_type1[3];
158static unsigned char gpio_int_type2[3];
158 159
159static void update_gpio_ab_int_params(int port) 160static void update_gpio_int_params(int abf)
160{ 161{
161 if (port == 0) { 162 if (abf == 0) {
162 __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE); 163 __raw_writeb(0, EP93XX_GPIO_A_INT_ENABLE);
163 __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2); 164 __raw_writeb(gpio_int_type2[0], EP93XX_GPIO_A_INT_TYPE2);
164 __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1); 165 __raw_writeb(gpio_int_type1[0], EP93XX_GPIO_A_INT_TYPE1);
165 __raw_writeb(gpio_int_enable[0], EP93XX_GPIO_A_INT_ENABLE); 166 __raw_writeb(gpio_int_unmasked[0] & gpio_int_enabled[0], EP93XX_GPIO_A_INT_ENABLE);
166 } else if (port == 1) { 167 } else if (abf == 1) {
167 __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE); 168 __raw_writeb(0, EP93XX_GPIO_B_INT_ENABLE);
168 __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2); 169 __raw_writeb(gpio_int_type2[1], EP93XX_GPIO_B_INT_TYPE2);
169 __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1); 170 __raw_writeb(gpio_int_type1[1], EP93XX_GPIO_B_INT_TYPE1);
170 __raw_writeb(gpio_int_enable[1], EP93XX_GPIO_B_INT_ENABLE); 171 __raw_writeb(gpio_int_unmasked[1] & gpio_int_enabled[1], EP93XX_GPIO_B_INT_ENABLE);
172 } else if (abf == 2) {
173 __raw_writeb(0, EP93XX_GPIO_F_INT_ENABLE);
174 __raw_writeb(gpio_int_type2[2], EP93XX_GPIO_F_INT_TYPE2);
175 __raw_writeb(gpio_int_type1[2], EP93XX_GPIO_F_INT_TYPE1);
176 __raw_writeb(gpio_int_unmasked[2] & gpio_int_enabled[2], EP93XX_GPIO_F_INT_ENABLE);
177 } else {
178 BUG();
171 } 179 }
172} 180}
173 181
@@ -192,8 +200,13 @@ void gpio_line_config(int line, int direction)
192 local_irq_save(flags); 200 local_irq_save(flags);
193 if (direction == GPIO_OUT) { 201 if (direction == GPIO_OUT) {
194 if (line >= 0 && line < 16) { 202 if (line >= 0 && line < 16) {
195 gpio_int_enable[line >> 3] &= ~(1 << (line & 7)); 203 /* Port A/B. */
196 update_gpio_ab_int_params(line >> 3); 204 gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
205 update_gpio_int_params(line >> 3);
206 } else if (line >= 40 && line < 48) {
207 /* Port F. */
208 gpio_int_unmasked[2] &= ~(1 << (line & 7));
209 update_gpio_int_params(2);
197 } 210 }
198 211
199 v = __raw_readb(data_direction_register); 212 v = __raw_readb(data_direction_register);
@@ -244,8 +257,7 @@ EXPORT_SYMBOL(gpio_line_set);
244/************************************************************************* 257/*************************************************************************
245 * EP93xx IRQ handling 258 * EP93xx IRQ handling
246 *************************************************************************/ 259 *************************************************************************/
247static void ep93xx_gpio_ab_irq_handler(unsigned int irq, 260static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
248 struct irq_desc *desc)
249{ 261{
250 unsigned char status; 262 unsigned char status;
251 int i; 263 int i;
@@ -267,37 +279,46 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq,
267 } 279 }
268} 280}
269 281
270static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq) 282static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
283{
284 int gpio_irq = IRQ_EP93XX_GPIO(16) + (((irq + 1) & 7) ^ 4);
285
286 desc_handle_irq(gpio_irq, irq_desc + gpio_irq);
287}
288
289static void ep93xx_gpio_irq_mask_ack(unsigned int irq)
271{ 290{
272 int line = irq - IRQ_EP93XX_GPIO(0); 291 int line = irq - IRQ_EP93XX_GPIO(0);
273 int port = line >> 3; 292 int port = line >> 3;
274 293
275 gpio_int_enable[port] &= ~(1 << (line & 7)); 294 gpio_int_unmasked[port] &= ~(1 << (line & 7));
276 update_gpio_ab_int_params(port); 295 update_gpio_int_params(port);
277 296
278 if (line >> 3) { 297 if (port == 0) {
279 __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
280 } else {
281 __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK); 298 __raw_writel(1 << (line & 7), EP93XX_GPIO_A_INT_ACK);
299 } else if (port == 1) {
300 __raw_writel(1 << (line & 7), EP93XX_GPIO_B_INT_ACK);
301 } else if (port == 2) {
302 __raw_writel(1 << (line & 7), EP93XX_GPIO_F_INT_ACK);
282 } 303 }
283} 304}
284 305
285static void ep93xx_gpio_ab_irq_mask(unsigned int irq) 306static void ep93xx_gpio_irq_mask(unsigned int irq)
286{ 307{
287 int line = irq - IRQ_EP93XX_GPIO(0); 308 int line = irq - IRQ_EP93XX_GPIO(0);
288 int port = line >> 3; 309 int port = line >> 3;
289 310
290 gpio_int_enable[port] &= ~(1 << (line & 7)); 311 gpio_int_unmasked[port] &= ~(1 << (line & 7));
291 update_gpio_ab_int_params(port); 312 update_gpio_int_params(port);
292} 313}
293 314
294static void ep93xx_gpio_ab_irq_unmask(unsigned int irq) 315static void ep93xx_gpio_irq_unmask(unsigned int irq)
295{ 316{
296 int line = irq - IRQ_EP93XX_GPIO(0); 317 int line = irq - IRQ_EP93XX_GPIO(0);
297 int port = line >> 3; 318 int port = line >> 3;
298 319
299 gpio_int_enable[port] |= 1 << (line & 7); 320 gpio_int_unmasked[port] |= 1 << (line & 7);
300 update_gpio_ab_int_params(port); 321 update_gpio_int_params(port);
301} 322}
302 323
303 324
@@ -306,40 +327,51 @@ static void ep93xx_gpio_ab_irq_unmask(unsigned int irq)
306 * edge (1) triggered, while gpio_int_type2 controls whether it 327 * edge (1) triggered, while gpio_int_type2 controls whether it
307 * triggers on low/falling (0) or high/rising (1). 328 * triggers on low/falling (0) or high/rising (1).
308 */ 329 */
309static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) 330static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type)
310{ 331{
311 int port; 332 int port;
312 int line; 333 int line;
313 334
314 line = irq - IRQ_EP93XX_GPIO(0); 335 line = irq - IRQ_EP93XX_GPIO(0);
315 gpio_line_config(line, GPIO_IN); 336 if (line >= 0 && line < 16) {
337 gpio_line_config(line, GPIO_IN);
338 } else {
339 gpio_line_config(EP93XX_GPIO_LINE_F(line), GPIO_IN);
340 }
316 341
317 port = line >> 3; 342 port = line >> 3;
318 line &= 7; 343 line &= 7;
319 344
320 if (type & IRQT_RISING) { 345 if (type & IRQT_RISING) {
346 gpio_int_enabled[port] |= 1 << line;
321 gpio_int_type1[port] |= 1 << line; 347 gpio_int_type1[port] |= 1 << line;
322 gpio_int_type2[port] |= 1 << line; 348 gpio_int_type2[port] |= 1 << line;
323 } else if (type & IRQT_FALLING) { 349 } else if (type & IRQT_FALLING) {
350 gpio_int_enabled[port] |= 1 << line;
324 gpio_int_type1[port] |= 1 << line; 351 gpio_int_type1[port] |= 1 << line;
325 gpio_int_type2[port] &= ~(1 << line); 352 gpio_int_type2[port] &= ~(1 << line);
326 } else if (type & IRQT_HIGH) { 353 } else if (type & IRQT_HIGH) {
354 gpio_int_enabled[port] |= 1 << line;
327 gpio_int_type1[port] &= ~(1 << line); 355 gpio_int_type1[port] &= ~(1 << line);
328 gpio_int_type2[port] |= 1 << line; 356 gpio_int_type2[port] |= 1 << line;
329 } else if (type & IRQT_LOW) { 357 } else if (type & IRQT_LOW) {
358 gpio_int_enabled[port] |= 1 << line;
330 gpio_int_type1[port] &= ~(1 << line); 359 gpio_int_type1[port] &= ~(1 << line);
331 gpio_int_type2[port] &= ~(1 << line); 360 gpio_int_type2[port] &= ~(1 << line);
361 } else {
362 gpio_int_enabled[port] &= ~(1 << line);
332 } 363 }
333 update_gpio_ab_int_params(port); 364 update_gpio_int_params(port);
334 365
335 return 0; 366 return 0;
336} 367}
337 368
338static struct irq_chip ep93xx_gpio_ab_irq_chip = { 369static struct irq_chip ep93xx_gpio_irq_chip = {
339 .ack = ep93xx_gpio_ab_irq_mask_ack, 370 .name = "GPIO",
340 .mask = ep93xx_gpio_ab_irq_mask, 371 .ack = ep93xx_gpio_irq_mask_ack,
341 .unmask = ep93xx_gpio_ab_irq_unmask, 372 .mask = ep93xx_gpio_irq_mask,
342 .set_type = ep93xx_gpio_ab_irq_type, 373 .unmask = ep93xx_gpio_irq_unmask,
374 .set_type = ep93xx_gpio_irq_type,
343}; 375};
344 376
345 377
@@ -350,12 +382,21 @@ void __init ep93xx_init_irq(void)
350 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); 382 vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK);
351 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); 383 vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK);
352 384
353 for (irq = IRQ_EP93XX_GPIO(0) ; irq <= IRQ_EP93XX_GPIO(15); irq++) { 385 for (irq = IRQ_EP93XX_GPIO(0); irq <= IRQ_EP93XX_GPIO(23); irq++) {
354 set_irq_chip(irq, &ep93xx_gpio_ab_irq_chip); 386 set_irq_chip(irq, &ep93xx_gpio_irq_chip);
355 set_irq_handler(irq, handle_level_irq); 387 set_irq_handler(irq, handle_level_irq);
356 set_irq_flags(irq, IRQF_VALID); 388 set_irq_flags(irq, IRQF_VALID);
357 } 389 }
390
358 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); 391 set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
392 set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
393 set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
394 set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
395 set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
396 set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
397 set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
398 set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
399 set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
359} 400}
360 401
361 402
@@ -461,8 +502,6 @@ void __init ep93xx_init_devices(void)
461{ 502{
462 unsigned int v; 503 unsigned int v;
463 504
464 ep93xx_clock_init();
465
466 /* 505 /*
467 * Disallow access to MaverickCrunch initially. 506 * Disallow access to MaverickCrunch initially.
468 */ 507 */
@@ -477,8 +516,4 @@ void __init ep93xx_init_devices(void)
477 516
478 platform_device_register(&ep93xx_rtc_device); 517 platform_device_register(&ep93xx_rtc_device);
479 platform_device_register(&ep93xx_ohci_device); 518 platform_device_register(&ep93xx_ohci_device);
480
481#ifdef CONFIG_CRUNCH
482 elf_hwcap |= HWCAP_CRUNCH;
483#endif
484} 519}
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 2499a7707e3c..966aa51aee09 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -120,6 +120,20 @@ static struct hw_pci n2100_pci __initdata = {
120 .map_irq = n2100_pci_map_irq, 120 .map_irq = n2100_pci_map_irq,
121}; 121};
122 122
123/*
124 * Both r8169 chips on the n2100 exhibit PCI parity problems. Set
125 * the ->broken_parity_status flag for both ports so that the r8169
126 * driver knows it should ignore error interrupts.
127 */
128static void n2100_fixup_r8169(struct pci_dev *dev)
129{
130 if (dev->bus->number == 0 &&
131 (dev->devfn == PCI_DEVFN(1, 0) ||
132 dev->devfn == PCI_DEVFN(2, 0)))
133 dev->broken_parity_status = 1;
134}
135DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169);
136
123static int __init n2100_pci_init(void) 137static int __init n2100_pci_init(void)
124{ 138{
125 if (machine_is_n2100()) 139 if (machine_is_n2100())
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 9de1278d234f..390524c4710f 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -338,6 +338,27 @@ static struct platform_device i2c_device = {
338 .num_resources = ARRAY_SIZE(i2c_resources), 338 .num_resources = ARRAY_SIZE(i2c_resources),
339}; 339};
340 340
341#ifdef CONFIG_PXA27x
342static struct resource i2c_power_resources[] = {
343 {
344 .start = 0x40f00180,
345 .end = 0x40f001a3,
346 .flags = IORESOURCE_MEM,
347 }, {
348 .start = IRQ_PWRI2C,
349 .end = IRQ_PWRI2C,
350 .flags = IORESOURCE_IRQ,
351 },
352};
353
354static struct platform_device i2c_power_device = {
355 .name = "pxa2xx-i2c",
356 .id = 1,
357 .resource = i2c_power_resources,
358 .num_resources = ARRAY_SIZE(i2c_resources),
359};
360#endif
361
341void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) 362void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
342{ 363{
343 i2c_device.dev.platform_data = info; 364 i2c_device.dev.platform_data = info;
@@ -392,6 +413,9 @@ static struct platform_device *devices[] __initdata = {
392 &stuart_device, 413 &stuart_device,
393 &pxaficp_device, 414 &pxaficp_device,
394 &i2c_device, 415 &i2c_device,
416#ifdef CONFIG_PXA27x
417 &i2c_power_device,
418#endif
395 &i2s_device, 419 &i2s_device,
396 &pxartc_device, 420 &pxartc_device,
397}; 421};
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 17f5f4439fe7..35156ca39df7 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -10,10 +10,21 @@ config MACH_REALVIEW_EB
10config REALVIEW_MPCORE 10config REALVIEW_MPCORE
11 bool "Support MPcore tile" 11 bool "Support MPcore tile"
12 depends on MACH_REALVIEW_EB 12 depends on MACH_REALVIEW_EB
13 select CACHE_L2X0
13 help 14 help
14 Enable support for the MPCore tile on the Realview platform. 15 Enable support for the MPCore tile on the Realview platform.
15 Since there are device address and interrupt differences, a 16 Since there are device address and interrupt differences, a
16 kernel built with this option enabled is not compatible with 17 kernel built with this option enabled is not compatible with
17 other tiles. 18 other tiles.
18 19
20config REALVIEW_MPCORE_REVB
21 bool "Support MPcore RevB tile"
22 depends on REALVIEW_MPCORE
23 default n
24 help
25 Enable support for the MPCore RevB tile on the Realview platform.
26 Since there are device address differences, a
27 kernel built with this option enabled is not compatible with
28 other tiles.
29
19endmenu 30endmenu
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index b8484e15dacb..fce3596f9950 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -52,13 +52,14 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
52 * core (e.g. timer irq), then they will not have been enabled 52 * core (e.g. timer irq), then they will not have been enabled
53 * for us: do so 53 * for us: do so
54 */ 54 */
55 gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); 55 gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
56 56
57 /* 57 /*
58 * let the primary processor know we're out of the 58 * let the primary processor know we're out of the
59 * pen, then head off into the C entry point 59 * pen, then head off into the C entry point
60 */ 60 */
61 pen_release = -1; 61 pen_release = -1;
62 smp_wmb();
62 63
63 /* 64 /*
64 * Synchronise with the boot thread. 65 * Synchronise with the boot thread.
@@ -102,6 +103,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
102 103
103 timeout = jiffies + (1 * HZ); 104 timeout = jiffies + (1 * HZ);
104 while (time_before(jiffies, timeout)) { 105 while (time_before(jiffies, timeout)) {
106 smp_rmb();
105 if (pen_release == -1) 107 if (pen_release == -1)
106 break; 108 break;
107 109
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 9741b4d3c9cf..3dba666151db 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -31,6 +31,7 @@
31#include <asm/mach-types.h> 31#include <asm/mach-types.h>
32#include <asm/hardware/gic.h> 32#include <asm/hardware/gic.h>
33#include <asm/hardware/icst307.h> 33#include <asm/hardware/icst307.h>
34#include <asm/hardware/cache-l2x0.h>
34 35
35#include <asm/mach/arch.h> 36#include <asm/mach/arch.h>
36#include <asm/mach/map.h> 37#include <asm/mach/map.h>
@@ -57,7 +58,26 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
57 .pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE), 58 .pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
58 .length = SZ_4K, 59 .length = SZ_4K,
59 .type = MT_DEVICE, 60 .type = MT_DEVICE,
61 },
62#ifdef CONFIG_REALVIEW_MPCORE
63 {
64 .virtual = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
65 .pfn = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
66 .length = SZ_4K,
67 .type = MT_DEVICE,
68 }, {
69 .virtual = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
70 .pfn = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
71 .length = SZ_4K,
72 .type = MT_DEVICE,
60 }, { 73 }, {
74 .virtual = IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
75 .pfn = __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
76 .length = SZ_8K,
77 .type = MT_DEVICE,
78 },
79#endif
80 {
61 .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE), 81 .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
62 .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE), 82 .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE),
63 .length = SZ_4K, 83 .length = SZ_4K,
@@ -138,19 +158,29 @@ static void __init gic_init_irq(void)
138#ifdef CONFIG_REALVIEW_MPCORE 158#ifdef CONFIG_REALVIEW_MPCORE
139 unsigned int pldctrl; 159 unsigned int pldctrl;
140 writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); 160 writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
141 pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + 0xd8); 161 pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
142 pldctrl |= 0x00800000; /* New irq mode */ 162 pldctrl |= 0x00800000; /* New irq mode */
143 writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8); 163 writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
144 writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); 164 writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
145#endif 165#endif
146 gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE)); 166 gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
147 gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); 167 gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
168#ifdef CONFIG_REALVIEW_MPCORE
169 gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
170 gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
171 gic_cascade_irq(1, IRQ_EB_IRQ1);
172#endif
148} 173}
149 174
150static void __init realview_eb_init(void) 175static void __init realview_eb_init(void)
151{ 176{
152 int i; 177 int i;
153 178
179#ifdef CONFIG_REALVIEW_MPCORE
180 /* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
181 * Bits: .... ...0 0111 1001 0000 .... .... .... */
182 l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff);
183#endif
154 clk_register(&realview_clcd_clk); 184 clk_register(&realview_clcd_clk);
155 185
156 platform_device_register(&realview_flash_device); 186 platform_device_register(&realview_flash_device);
diff --git a/arch/arm/mach-s3c2400/Kconfig b/arch/arm/mach-s3c2400/Kconfig
new file mode 100644
index 000000000000..deab0722836e
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Kconfig
@@ -0,0 +1,13 @@
1# arch/arm/mach-s3c2400/Kconfig
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7
8
9menu "S3C2400 Machines"
10
11
12endmenu
13
diff --git a/arch/arm/mach-s3c2400/Makefile b/arch/arm/mach-s3c2400/Makefile
new file mode 100644
index 000000000000..7e23f4e13766
--- /dev/null
+++ b/arch/arm/mach-s3c2400/Makefile
@@ -0,0 +1,15 @@
1# arch/arm/mach-s3c2400/Makefile
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7obj-y :=
8obj-m :=
9obj-n :=
10obj- :=
11
12obj-$(CONFIG_CPU_S3C2400) += gpio.o
13
14# Machine support
15
diff --git a/arch/arm/mach-s3c2410/s3c2400-gpio.c b/arch/arm/mach-s3c2400/gpio.c
index 1576d01d5f82..758e160410e9 100644
--- a/arch/arm/mach-s3c2410/s3c2400-gpio.c
+++ b/arch/arm/mach-s3c2400/gpio.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2400-gpio.c 1/* linux/arch/arm/mach-s3c2400/gpio.c
2 * 2 *
3 * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org> 3 * Copyright (c) 2006 Lucas Correia Villa Real <lucasvr@gobolinux.org>
4 * 4 *
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index eb4ec411312b..d4b013b283c3 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -1,54 +1,51 @@
1if ARCH_S3C2410 1# arch/arm/mach-s3c2410/Kconfig
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
2 6
3menu "S3C24XX Implementations" 7config CPU_S3C2410
8 bool
9 depends on ARCH_S3C2410
10 select S3C2410_CLOCK
11 select S3C2410_GPIO
12 select S3C2410_PM if PM
13 help
14 Support for S3C2410 and S3C2410A family from the S3C24XX line
15 of Samsung Mobile CPUs.
4 16
5config MACH_AML_M5900 17config CPU_S3C2410_DMA
6 bool "AML M5900 Series" 18 bool
7 select CPU_S3C2410 19 depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
8 select PM_SIMTEC if PM 20 default y if CPU_S3C2410 || CPU_S3C2442
9 help 21 help
10 Say Y here if you are using the American Microsystems M5900 Series 22 DMA device selection for S3C2410 and compatible CPUs
11 <http://www.amltd.com>
12 23
13config MACH_ANUBIS 24config S3C2410_PM
14 bool "Simtec Electronics ANUBIS" 25 bool
15 select CPU_S3C2440
16 select PM_SIMTEC if PM
17 help 26 help
18 Say Y here if you are using the Simtec Electronics ANUBIS 27 Power Management code common to S3C2410 and better
19 development system
20 28
21config MACH_OSIRIS 29config S3C2410_GPIO
22 bool "Simtec IM2440D20 (OSIRIS) module" 30 bool
23 select CPU_S3C2440
24 select PM_SIMTEC if PM
25 help 31 help
26 Say Y here if you are using the Simtec IM2440D20 module, also 32 GPIO code for S3C2410 and similar processors
27 known as the Osiris.
28 33
29config ARCH_BAST 34config S3C2410_CLOCK
30 bool "Simtec Electronics BAST (EB2410ITX)" 35 bool
31 select CPU_S3C2410
32 select PM_SIMTEC if PM
33 select ISA
34 help 36 help
35 Say Y here if you are using the Simtec Electronics EB2410ITX 37 Clock code for the S3C2410, and similar processors
36 development board (also known as BAST)
37 38
38 Product page: <http://www.simtec.co.uk/products/EB2410ITX/>.
39 39
40config BAST_PC104_IRQ 40menu "S3C2410 Machines"
41 bool "BAST PC104 IRQ support"
42 depends on ARCH_BAST
43 default y
44 help
45 Say Y here to enable the PC104 IRQ routing on the
46 Simtec BAST (EB2410ITX)
47 41
48config PM_H1940 42config ARCH_SMDK2410
49 bool 43 bool "SMDK2410/A9M2410"
44 select CPU_S3C2410
45 select MACH_SMDK
50 help 46 help
51 Internal node for H1940 and related PM 47 Say Y here if you are using the SMDK2410 or the derived module A9M2410
48 <http://www.fsforth.de>
52 49
53config ARCH_H1940 50config ARCH_H1940
54 bool "IPAQ H1940" 51 bool "IPAQ H1940"
@@ -57,7 +54,10 @@ config ARCH_H1940
57 help 54 help
58 Say Y here if you are using the HP IPAQ H1940 55 Say Y here if you are using the HP IPAQ H1940
59 56
60 <http://www.handhelds.org/projects/h1940.html>. 57config PM_H1940
58 bool
59 help
60 Internal node for H1940 and related PM
61 61
62config MACH_N30 62config MACH_N30
63 bool "Acer N30" 63 bool "Acer N30"
@@ -65,53 +65,36 @@ config MACH_N30
65 help 65 help
66 Say Y here if you are using the Acer N30 66 Say Y here if you are using the Acer N30
67 67
68 <http://zoo.weinigel.se/n30>. 68config ARCH_BAST
69 69 bool "Simtec Electronics BAST (EB2410ITX)"
70config MACH_SMDK
71 bool
72 help
73 Common machine code for SMDK2410 and SMDK2440
74
75config ARCH_SMDK2410
76 bool "SMDK2410/A9M2410"
77 select CPU_S3C2410 70 select CPU_S3C2410
78 select MACH_SMDK 71 select PM_SIMTEC if PM
72 select ISA
79 help 73 help
80 Say Y here if you are using the SMDK2410 or the derived module A9M2410 74 Say Y here if you are using the Simtec Electronics EB2410ITX
81 <http://www.fsforth.de> 75 development board (also known as BAST)
82 76
83config ARCH_S3C2440 77config MACH_OTOM
84 bool "SMDK2440" 78 bool "NexVision OTOM Board"
85 select CPU_S3C2440 79 select CPU_S3C2410
86 select MACH_SMDK
87 help 80 help
88 Say Y here if you are using the SMDK2440. 81 Say Y here if you are using the Nex Vision OTOM board
89
90config SMDK2440_CPU2440
91 bool "SMDK2440 with S3C2440 CPU module"
92 depends on ARCH_S3C2440
93 default y if ARCH_S3C2440
94 select CPU_S3C2440
95
96config SMDK2440_CPU2442
97 bool "SMDM2440 with S3C2442 CPU module"
98 depends on ARCH_S3C2440
99 select CPU_S3C2442
100 82
101config MACH_S3C2413 83config MACH_AML_M5900
102 bool 84 bool "AML M5900 Series"
85 select CPU_S3C2410
86 select PM_SIMTEC if PM
103 help 87 help
104 Internal node for S3C2413 version of SMDK2413, so that 88 Say Y here if you are using the American Microsystems M5900 Series
105 machine_is_s3c2413() will work when MACH_SMDK2413 is 89 <http://www.amltd.com>
106 selected
107 90
108config MACH_SMDK2413 91config BAST_PC104_IRQ
109 bool "SMDK2413" 92 bool "BAST PC104 IRQ support"
110 select CPU_S3C2412 93 depends on ARCH_BAST
111 select MACH_S3C2413 94 default y
112 select MACH_SMDK
113 help 95 help
114 Say Y here if you are using an SMDK2413 96 Say Y here to enable the PC104 IRQ routing on the
97 Simtec BAST (EB2410ITX)
115 98
116config MACH_VR1000 99config MACH_VR1000
117 bool "Thorcom VR1000" 100 bool "Thorcom VR1000"
@@ -120,202 +103,11 @@ config MACH_VR1000
120 help 103 help
121 Say Y here if you are using the Thorcom VR1000 board. 104 Say Y here if you are using the Thorcom VR1000 board.
122 105
123 This linux port is currently being maintained by Simtec, on behalf 106config MACH_QT2410
124 of Thorcom. Any queries, please contact Thorcom first. 107 bool "QT2410"
125 108 select CPU_S3C2410
126config MACH_RX3715
127 bool "HP iPAQ rx3715"
128 select CPU_S3C2440
129 select PM_H1940 if PM
130 help
131 Say Y here if you are using the HP iPAQ rx3715.
132
133 See <http://www.handhelds.org/projects/rx3715.html> for more
134 information on this project
135
136config MACH_OTOM
137 bool "NexVision OTOM Board"
138 select CPU_S3C2410
139 help
140 Say Y here if you are using the Nex Vision OTOM board
141
142config MACH_NEXCODER_2440
143 bool "NexVision NEXCODER 2440 Light Board"
144 select CPU_S3C2440
145 help
146 Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
147
148config MACH_VSTMS
149 bool "VMSTMS"
150 select CPU_S3C2412
151 help 109 help
152 Say Y here if you are using an VSTMS board 110 Say Y here if you are using the Armzone QT2410
153 111
154endmenu 112endmenu
155 113
156config S3C2410_CLOCK
157 bool
158 help
159 Clock code for the S3C2410, and similar processors
160
161config S3C2410_PM
162 bool
163 help
164 Power Management code common to S3C2410 and better
165
166config CPU_S3C2410_DMA
167 bool
168 depends on S3C2410_DMA && (CPU_S3C2410 || CPU_S3C2442)
169 default y if CPU_S3C2410 || CPU_S3C2442
170 help
171 DMA device selection for S3C2410 and compatible CPUs
172
173config CPU_S3C2410
174 bool
175 depends on ARCH_S3C2410
176 select S3C2410_CLOCK
177 select S3C2410_PM if PM
178 help
179 Support for S3C2410 and S3C2410A family from the S3C24XX line
180 of Samsung Mobile CPUs.
181
182# internal node to signify if we are only dealing with an S3C2412
183
184config CPU_S3C2412_ONLY
185 bool
186 depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
187 !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
188 default y if CPU_S3C2412
189
190config S3C2412_PM
191 bool
192 help
193 Internal config node to apply S3C2412 power management
194
195config CPU_S3C2412
196 bool
197 depends on ARCH_S3C2410
198 select S3C2412_PM if PM
199 help
200 Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
201
202config CPU_S3C244X
203 bool
204 depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
205 help
206 Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
207
208config CPU_S3C2440
209 bool
210 depends on ARCH_S3C2410
211 select S3C2410_CLOCK
212 select S3C2410_PM if PM
213 select CPU_S3C244X
214 help
215 Support for S3C2440 Samsung Mobile CPU based systems.
216
217config CPU_S3C2442
218 bool
219 depends on ARCH_S3C2420
220 select S3C2410_CLOCK
221 select S3C2410_PM if PM
222 select CPU_S3C244X
223 help
224 Support for S3C2442 Samsung Mobile CPU based systems.
225
226comment "S3C2410 Boot"
227
228config S3C2410_BOOT_WATCHDOG
229 bool "S3C2410 Initialisation watchdog"
230 depends on ARCH_S3C2410 && S3C2410_WATCHDOG
231 help
232 Say y to enable the watchdog during the kernel decompression
233 stage. If the kernel fails to uncompress, then the watchdog
234 will trigger a reset and the system should restart.
235
236 Although this uses the same hardware unit as the kernel watchdog
237 driver, it is not a replacement for it. If you use this option,
238 you will have to use the watchdg driver to either stop the timeout
239 or restart it. If you do not, then your kernel will reboot after
240 startup.
241
242 The driver uses a fixed timeout value, so the exact time till the
243 system resets depends on the value of PCLK. The timeout on an
244 200MHz s3c2410 should be about 30 seconds.
245
246config S3C2410_BOOT_ERROR_RESET
247 bool "S3C2410 Reboot on decompression error"
248 depends on ARCH_S3C2410
249 help
250 Say y here to use the watchdog to reset the system if the
251 kernel decompressor detects an error during decompression.
252
253
254comment "S3C2410 Setup"
255
256config S3C2410_DMA
257 bool "S3C2410 DMA support"
258 depends on ARCH_S3C2410
259 help
260 S3C2410 DMA support. This is needed for drivers like sound which
261 use the S3C2410's DMA system to move data to and from the
262 peripheral blocks.
263
264config S3C2410_DMA_DEBUG
265 bool "S3C2410 DMA support debug"
266 depends on ARCH_S3C2410 && S3C2410_DMA
267 help
268 Enable debugging output for the DMA code. This option sends info
269 to the kernel log, at priority KERN_DEBUG.
270
271 Note, it is easy to create and fill the log buffer in a small
272 amount of time, as well as using an significant percentage of
273 the CPU time doing so.
274
275
276config S3C2410_PM_DEBUG
277 bool "S3C2410 PM Suspend debug"
278 depends on ARCH_S3C2410 && PM
279 help
280 Say Y here if you want verbose debugging from the PM Suspend and
281 Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
282 for more information.
283
284config S3C2410_PM_CHECK
285 bool "S3C2410 PM Suspend Memory CRC"
286 depends on ARCH_S3C2410 && PM && CRC32
287 help
288 Enable the PM code's memory area checksum over sleep. This option
289 will generate CRCs of all blocks of memory, and store them before
290 going to sleep. The blocks are then checked on resume for any
291 errors.
292
293config S3C2410_PM_CHECK_CHUNKSIZE
294 int "S3C2410 PM Suspend CRC Chunksize (KiB)"
295 depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
296 default 64
297 help
298 Set the chunksize in Kilobytes of the CRC for checking memory
299 corruption over suspend and resume. A smaller value will mean that
300 the CRC data block will take more memory, but wil identify any
301 faults with better precision.
302
303config PM_SIMTEC
304 bool
305 help
306 Common power management code for systems that are
307 compatible with the Simtec style of power management
308
309config S3C2410_LOWLEVEL_UART_PORT
310 int "S3C2410 UART to use for low-level messages"
311 default 0
312 help
313 Choice of which UART port to use for the low-level messages,
314 such as the `Uncompressing...` at start time. The value of
315 this configuration should be between zero and two. The port
316 must have been initialised by the boot-loader before use.
317
318 Note, this does not affect the port used by the debug messages,
319 which is a separate configuration.
320
321endif
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 27663e28cc88..9a3d3d24c084 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -1,92 +1,31 @@
1 1# arch/arm/mach-s3c2410/Makefile
2# 2#
3# Makefile for the linux kernel. 3# Copyright 2007 Simtec Electronics
4# 4#
5# Licensed under GPLv2
5 6
6# Object file lists. 7obj-y :=
7 8obj-m :=
8obj-y := cpu.o irq.o time.o gpio.o clock.o devs.o 9obj-n :=
9obj-m := 10obj- :=
10obj-n :=
11obj- :=
12obj-dma-y :=
13obj-dma-n :=
14
15# DMA
16obj-$(CONFIG_S3C2410_DMA) += dma.o
17
18# S3C2400 support files
19obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o
20
21# S3C2410 support files
22 11
23obj-$(CONFIG_CPU_S3C2410) += s3c2410.o 12obj-$(CONFIG_CPU_S3C2410) += s3c2410.o
24obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o 13obj-$(CONFIG_CPU_S3C2410) += irq.o
25obj-$(CONFIG_CPU_S3C2410) += s3c2410-irq.o 14obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
26 15obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
27obj-$(CONFIG_S3C2410_PM) += s3c2410-pm.o s3c2410-sleep.o 16obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o
28obj-$(CONFIG_CPU_S3C2410_DMA) += s3c2410-dma.o 17obj-$(CONFIG_S3C2410_GPIO) += gpio.o
29 18obj-$(CONFIG_S3C2410_CLOCK) += clock.o
30# Power Management support
31
32obj-$(CONFIG_PM) += pm.o sleep.o
33obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
34obj-$(CONFIG_PM_H1940) += pm-h1940.o
35
36# S3C2412 support
37obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
38obj-$(CONFIG_CPU_S3C2412) += s3c2412-irq.o
39obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o
40obj-dma-$(CONFIG_CPU_S3C2412) += s3c2412-dma.o
41
42obj-$(CONFIG_S3C2412_PM) += s3c2412-pm.o
43
44#
45# S3C244X support
46
47obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
48obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o
49
50# Clock control
51
52obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
53
54# S3C2440 support
55
56obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
57obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o
58obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o
59obj-$(CONFIG_CPU_S3C2440) += s3c2410-gpio.o
60obj-dma-$(CONFIG_CPU_S3C2440) += s3c2440-dma.o
61 19
62# S3C2442 support 20# Machine support
63 21
64obj-$(CONFIG_CPU_S3C2442) += s3c2442.o 22obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
65obj-$(CONFIG_CPU_S3C2442) += s3c2442-clock.o
66
67# bast extras
68
69obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
70
71# merge in dma objects
72
73obj-y += $(obj-dma-y)
74
75# machine specific support
76
77obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o
78obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
79obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
80obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
81obj-$(CONFIG_ARCH_H1940) += mach-h1940.o 23obj-$(CONFIG_ARCH_H1940) += mach-h1940.o
24obj-$(CONFIG_PM_H1940) += pm-h1940.o
82obj-$(CONFIG_MACH_N30) += mach-n30.o 25obj-$(CONFIG_MACH_N30) += mach-n30.o
83obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o 26obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o
84obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o
85obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
86obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
87obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
88obj-$(CONFIG_MACH_OTOM) += mach-otom.o 27obj-$(CONFIG_MACH_OTOM) += mach-otom.o
89obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o 28obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o
90obj-$(CONFIG_MACH_VSTMS) += mach-vstms.o 29obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o
91 30obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o
92obj-$(CONFIG_MACH_SMDK) += common-smdk.o \ No newline at end of file 31obj-$(CONFIG_MACH_QT2410) += mach-qt2410.o
diff --git a/arch/arm/mach-s3c2410/bast-irq.c b/arch/arm/mach-s3c2410/bast-irq.c
index 379efe70778c..daeba427d781 100644
--- a/arch/arm/mach-s3c2410/bast-irq.c
+++ b/arch/arm/mach-s3c2410/bast-irq.c
@@ -39,7 +39,7 @@
39#include <asm/arch/bast-map.h> 39#include <asm/arch/bast-map.h>
40#include <asm/arch/bast-irq.h> 40#include <asm/arch/bast-irq.h>
41 41
42#include "irq.h" 42#include <asm/plat-s3c24xx/irq.h>
43 43
44#if 0 44#if 0
45#include <asm/debug-ll.h> 45#include <asm/debug-ll.h>
diff --git a/arch/arm/mach-s3c2410/bast.h b/arch/arm/mach-s3c2410/bast.h
index e5d03311752c..e98543742eb9 100644
--- a/arch/arm/mach-s3c2410/bast.h
+++ b/arch/arm/mach-s3c2410/bast.h
@@ -1,2 +1,2 @@
1 1/* linux/arch/arm/mach-s3c2410/bast.h
2extern void bast_init_irq(void); 2extern void bast_init_irq(void);
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index e13fb6778890..5b4831c4c1d8 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -1,15 +1,9 @@
1/* linux/arch/arm/mach-s3c2410/clock.c 1/* linux/arch/arm/mach-s3c2410/clock.c
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * S3C24XX Core clock control support 6 * S3C2410,S3C2440,S3C2442 Clock control support
7 *
8 * Based on, and code from linux/arch/arm/mach-versatile/clock.c
9 **
10 ** Copyright (C) 2004 ARM Limited.
11 ** Written by Deep Blue Solutions Limited.
12 *
13 * 7 *
14 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -32,418 +26,251 @@
32#include <linux/list.h> 26#include <linux/list.h>
33#include <linux/errno.h> 27#include <linux/errno.h>
34#include <linux/err.h> 28#include <linux/err.h>
35#include <linux/platform_device.h>
36#include <linux/sysdev.h> 29#include <linux/sysdev.h>
37#include <linux/interrupt.h>
38#include <linux/ioport.h>
39#include <linux/clk.h> 30#include <linux/clk.h>
40#include <linux/mutex.h> 31#include <linux/mutex.h>
41#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/serial_core.h>
34
35#include <asm/mach/map.h>
42 36
43#include <asm/hardware.h> 37#include <asm/hardware.h>
44#include <asm/irq.h>
45#include <asm/io.h> 38#include <asm/io.h>
46 39
40#include <asm/arch/regs-serial.h>
47#include <asm/arch/regs-clock.h> 41#include <asm/arch/regs-clock.h>
48#include <asm/arch/regs-gpio.h> 42#include <asm/arch/regs-gpio.h>
49 43
50#include "clock.h" 44#include <asm/plat-s3c24xx/s3c2410.h>
51#include "cpu.h" 45#include <asm/plat-s3c24xx/clock.h>
52 46#include <asm/plat-s3c24xx/cpu.h>
53/* clock information */
54 47
55static LIST_HEAD(clocks); 48int s3c2410_clkcon_enable(struct clk *clk, int enable)
56
57DEFINE_MUTEX(clocks_mutex);
58
59/* enable and disable calls for use with the clk struct */
60
61static int clk_null_enable(struct clk *clk, int enable)
62{ 49{
63 return 0; 50 unsigned int clocks = clk->ctrlbit;
64} 51 unsigned long clkcon;
65
66/* Clock API calls */
67 52
68struct clk *clk_get(struct device *dev, const char *id) 53 clkcon = __raw_readl(S3C2410_CLKCON);
69{
70 struct clk *p;
71 struct clk *clk = ERR_PTR(-ENOENT);
72 int idno;
73 54
74 if (dev == NULL || dev->bus != &platform_bus_type) 55 if (enable)
75 idno = -1; 56 clkcon |= clocks;
76 else 57 else
77 idno = to_platform_device(dev)->id; 58 clkcon &= ~clocks;
78
79 mutex_lock(&clocks_mutex);
80
81 list_for_each_entry(p, &clocks, list) {
82 if (p->id == idno &&
83 strcmp(id, p->name) == 0 &&
84 try_module_get(p->owner)) {
85 clk = p;
86 break;
87 }
88 }
89
90 /* check for the case where a device was supplied, but the
91 * clock that was being searched for is not device specific */
92
93 if (IS_ERR(clk)) {
94 list_for_each_entry(p, &clocks, list) {
95 if (p->id == -1 && strcmp(id, p->name) == 0 &&
96 try_module_get(p->owner)) {
97 clk = p;
98 break;
99 }
100 }
101 }
102 59
103 mutex_unlock(&clocks_mutex); 60 /* ensure none of the special function bits set */
104 return clk; 61 clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
105}
106 62
107void clk_put(struct clk *clk) 63 __raw_writel(clkcon, S3C2410_CLKCON);
108{
109 module_put(clk->owner);
110}
111 64
112int clk_enable(struct clk *clk)
113{
114 if (IS_ERR(clk) || clk == NULL)
115 return -EINVAL;
116
117 clk_enable(clk->parent);
118
119 mutex_lock(&clocks_mutex);
120
121 if ((clk->usage++) == 0)
122 (clk->enable)(clk, 1);
123
124 mutex_unlock(&clocks_mutex);
125 return 0; 65 return 0;
126} 66}
127 67
128void clk_disable(struct clk *clk) 68static int s3c2410_upll_enable(struct clk *clk, int enable)
129{
130 if (IS_ERR(clk) || clk == NULL)
131 return;
132
133 mutex_lock(&clocks_mutex);
134
135 if ((--clk->usage) == 0)
136 (clk->enable)(clk, 0);
137
138 mutex_unlock(&clocks_mutex);
139 clk_disable(clk->parent);
140}
141
142
143unsigned long clk_get_rate(struct clk *clk)
144{
145 if (IS_ERR(clk))
146 return 0;
147
148 if (clk->rate != 0)
149 return clk->rate;
150
151 if (clk->get_rate != NULL)
152 return (clk->get_rate)(clk);
153
154 if (clk->parent != NULL)
155 return clk_get_rate(clk->parent);
156
157 return clk->rate;
158}
159
160long clk_round_rate(struct clk *clk, unsigned long rate)
161{
162 if (!IS_ERR(clk) && clk->round_rate)
163 return (clk->round_rate)(clk, rate);
164
165 return rate;
166}
167
168int clk_set_rate(struct clk *clk, unsigned long rate)
169{
170 int ret;
171
172 if (IS_ERR(clk))
173 return -EINVAL;
174
175 mutex_lock(&clocks_mutex);
176 ret = (clk->set_rate)(clk, rate);
177 mutex_unlock(&clocks_mutex);
178
179 return ret;
180}
181
182struct clk *clk_get_parent(struct clk *clk)
183{ 69{
184 return clk->parent; 70 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
185} 71 unsigned long orig = clkslow;
186
187int clk_set_parent(struct clk *clk, struct clk *parent)
188{
189 int ret = 0;
190
191 if (IS_ERR(clk))
192 return -EINVAL;
193
194 mutex_lock(&clocks_mutex);
195
196 if (clk->set_parent)
197 ret = (clk->set_parent)(clk, parent);
198
199 mutex_unlock(&clocks_mutex);
200
201 return ret;
202}
203
204EXPORT_SYMBOL(clk_get);
205EXPORT_SYMBOL(clk_put);
206EXPORT_SYMBOL(clk_enable);
207EXPORT_SYMBOL(clk_disable);
208EXPORT_SYMBOL(clk_get_rate);
209EXPORT_SYMBOL(clk_round_rate);
210EXPORT_SYMBOL(clk_set_rate);
211EXPORT_SYMBOL(clk_get_parent);
212EXPORT_SYMBOL(clk_set_parent);
213
214/* base clocks */
215
216struct clk clk_xtal = {
217 .name = "xtal",
218 .id = -1,
219 .rate = 0,
220 .parent = NULL,
221 .ctrlbit = 0,
222};
223
224struct clk clk_mpll = {
225 .name = "mpll",
226 .id = -1,
227};
228
229struct clk clk_upll = {
230 .name = "upll",
231 .id = -1,
232 .parent = NULL,
233 .ctrlbit = 0,
234};
235
236struct clk clk_f = {
237 .name = "fclk",
238 .id = -1,
239 .rate = 0,
240 .parent = &clk_mpll,
241 .ctrlbit = 0,
242};
243
244struct clk clk_h = {
245 .name = "hclk",
246 .id = -1,
247 .rate = 0,
248 .parent = NULL,
249 .ctrlbit = 0,
250};
251
252struct clk clk_p = {
253 .name = "pclk",
254 .id = -1,
255 .rate = 0,
256 .parent = NULL,
257 .ctrlbit = 0,
258};
259
260struct clk clk_usb_bus = {
261 .name = "usb-bus",
262 .id = -1,
263 .rate = 0,
264 .parent = &clk_upll,
265};
266
267/* clocks that could be registered by external code */
268
269static int s3c24xx_dclk_enable(struct clk *clk, int enable)
270{
271 unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
272 72
273 if (enable) 73 if (enable)
274 dclkcon |= clk->ctrlbit; 74 clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
275 else 75 else
276 dclkcon &= ~clk->ctrlbit; 76 clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
277 77
278 __raw_writel(dclkcon, S3C24XX_DCLKCON); 78 __raw_writel(clkslow, S3C2410_CLKSLOW);
279 79
280 return 0; 80 /* if we started the UPLL, then allow to settle */
281}
282 81
283static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) 82 if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
284{ 83 udelay(200);
285 unsigned long dclkcon;
286 unsigned int uclk;
287
288 if (parent == &clk_upll)
289 uclk = 1;
290 else if (parent == &clk_p)
291 uclk = 0;
292 else
293 return -EINVAL;
294
295 clk->parent = parent;
296
297 dclkcon = __raw_readl(S3C24XX_DCLKCON);
298
299 if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
300 if (uclk)
301 dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
302 else
303 dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
304 } else {
305 if (uclk)
306 dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
307 else
308 dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
309 }
310
311 __raw_writel(dclkcon, S3C24XX_DCLKCON);
312 84
313 return 0; 85 return 0;
314} 86}
315 87
316 88/* standard clock definitions */
317static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) 89
318{ 90static struct clk init_clocks_disable[] = {
319 unsigned long mask; 91 {
320 unsigned long source; 92 .name = "nand",
321 93 .id = -1,
322 /* calculate the MISCCR setting for the clock */ 94 .parent = &clk_h,
323 95 .enable = s3c2410_clkcon_enable,
324 if (parent == &clk_xtal) 96 .ctrlbit = S3C2410_CLKCON_NAND,
325 source = S3C2410_MISCCR_CLK0_MPLL; 97 }, {
326 else if (parent == &clk_upll) 98 .name = "sdi",
327 source = S3C2410_MISCCR_CLK0_UPLL; 99 .id = -1,
328 else if (parent == &clk_f) 100 .parent = &clk_p,
329 source = S3C2410_MISCCR_CLK0_FCLK; 101 .enable = s3c2410_clkcon_enable,
330 else if (parent == &clk_h) 102 .ctrlbit = S3C2410_CLKCON_SDI,
331 source = S3C2410_MISCCR_CLK0_HCLK; 103 }, {
332 else if (parent == &clk_p) 104 .name = "adc",
333 source = S3C2410_MISCCR_CLK0_PCLK; 105 .id = -1,
334 else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) 106 .parent = &clk_p,
335 source = S3C2410_MISCCR_CLK0_DCLK0; 107 .enable = s3c2410_clkcon_enable,
336 else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) 108 .ctrlbit = S3C2410_CLKCON_ADC,
337 source = S3C2410_MISCCR_CLK0_DCLK0; 109 }, {
338 else 110 .name = "i2c",
339 return -EINVAL; 111 .id = -1,
340 112 .parent = &clk_p,
341 clk->parent = parent; 113 .enable = s3c2410_clkcon_enable,
342 114 .ctrlbit = S3C2410_CLKCON_IIC,
343 if (clk == &s3c24xx_dclk0) 115 }, {
344 mask = S3C2410_MISCCR_CLK0_MASK; 116 .name = "iis",
345 else { 117 .id = -1,
346 source <<= 4; 118 .parent = &clk_p,
347 mask = S3C2410_MISCCR_CLK1_MASK; 119 .enable = s3c2410_clkcon_enable,
120 .ctrlbit = S3C2410_CLKCON_IIS,
121 }, {
122 .name = "spi",
123 .id = -1,
124 .parent = &clk_p,
125 .enable = s3c2410_clkcon_enable,
126 .ctrlbit = S3C2410_CLKCON_SPI,
348 } 127 }
349
350 s3c2410_modify_misccr(mask, source);
351 return 0;
352}
353
354/* external clock definitions */
355
356struct clk s3c24xx_dclk0 = {
357 .name = "dclk0",
358 .id = -1,
359 .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
360 .enable = s3c24xx_dclk_enable,
361 .set_parent = s3c24xx_dclk_setparent,
362};
363
364struct clk s3c24xx_dclk1 = {
365 .name = "dclk1",
366 .id = -1,
367 .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
368 .enable = s3c24xx_dclk_enable,
369 .set_parent = s3c24xx_dclk_setparent,
370}; 128};
371 129
372struct clk s3c24xx_clkout0 = { 130static struct clk init_clocks[] = {
373 .name = "clkout0", 131 {
374 .id = -1, 132 .name = "lcd",
375 .set_parent = s3c24xx_clkout_setparent, 133 .id = -1,
134 .parent = &clk_h,
135 .enable = s3c2410_clkcon_enable,
136 .ctrlbit = S3C2410_CLKCON_LCDC,
137 }, {
138 .name = "gpio",
139 .id = -1,
140 .parent = &clk_p,
141 .enable = s3c2410_clkcon_enable,
142 .ctrlbit = S3C2410_CLKCON_GPIO,
143 }, {
144 .name = "usb-host",
145 .id = -1,
146 .parent = &clk_h,
147 .enable = s3c2410_clkcon_enable,
148 .ctrlbit = S3C2410_CLKCON_USBH,
149 }, {
150 .name = "usb-device",
151 .id = -1,
152 .parent = &clk_h,
153 .enable = s3c2410_clkcon_enable,
154 .ctrlbit = S3C2410_CLKCON_USBD,
155 }, {
156 .name = "timers",
157 .id = -1,
158 .parent = &clk_p,
159 .enable = s3c2410_clkcon_enable,
160 .ctrlbit = S3C2410_CLKCON_PWMT,
161 }, {
162 .name = "uart",
163 .id = 0,
164 .parent = &clk_p,
165 .enable = s3c2410_clkcon_enable,
166 .ctrlbit = S3C2410_CLKCON_UART0,
167 }, {
168 .name = "uart",
169 .id = 1,
170 .parent = &clk_p,
171 .enable = s3c2410_clkcon_enable,
172 .ctrlbit = S3C2410_CLKCON_UART1,
173 }, {
174 .name = "uart",
175 .id = 2,
176 .parent = &clk_p,
177 .enable = s3c2410_clkcon_enable,
178 .ctrlbit = S3C2410_CLKCON_UART2,
179 }, {
180 .name = "rtc",
181 .id = -1,
182 .parent = &clk_p,
183 .enable = s3c2410_clkcon_enable,
184 .ctrlbit = S3C2410_CLKCON_RTC,
185 }, {
186 .name = "watchdog",
187 .id = -1,
188 .parent = &clk_p,
189 .ctrlbit = 0,
190 }, {
191 .name = "usb-bus-host",
192 .id = -1,
193 .parent = &clk_usb_bus,
194 }, {
195 .name = "usb-bus-gadget",
196 .id = -1,
197 .parent = &clk_usb_bus,
198 },
376}; 199};
377 200
378struct clk s3c24xx_clkout1 = { 201/* s3c2410_baseclk_add()
379 .name = "clkout1", 202 *
380 .id = -1, 203 * Add all the clocks used by the s3c2410 or compatible CPUs
381 .set_parent = s3c24xx_clkout_setparent, 204 * such as the S3C2440 and S3C2442.
382}; 205 *
383 206 * We cannot use a system device as we are needed before any
384struct clk s3c24xx_uclk = { 207 * of the init-calls that initialise the devices are actually
385 .name = "uclk", 208 * done.
386 .id = -1, 209*/
387};
388
389/* initialise the clock system */
390
391int s3c24xx_register_clock(struct clk *clk)
392{
393 clk->owner = THIS_MODULE;
394
395 if (clk->enable == NULL)
396 clk->enable = clk_null_enable;
397
398 /* add to the list of available clocks */
399
400 mutex_lock(&clocks_mutex);
401 list_add(&clk->list, &clocks);
402 mutex_unlock(&clocks_mutex);
403
404 return 0;
405}
406
407/* initalise all the clocks */
408 210
409int __init s3c24xx_setup_clocks(unsigned long xtal, 211int __init s3c2410_baseclk_add(void)
410 unsigned long fclk,
411 unsigned long hclk,
412 unsigned long pclk)
413{ 212{
414 printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n"); 213 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
214 unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
215 struct clk *clkp;
216 struct clk *xtal;
217 int ret;
218 int ptr;
415 219
416 /* initialise the main system clocks */ 220 clk_upll.enable = s3c2410_upll_enable;
417 221
418 clk_xtal.rate = xtal; 222 if (s3c24xx_register_clock(&clk_usb_bus) < 0)
419 clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal); 223 printk(KERN_ERR "failed to register usb bus clock\n");
420 224
421 clk_mpll.rate = fclk; 225 /* register clocks from clock array */
422 clk_h.rate = hclk;
423 clk_p.rate = pclk;
424 clk_f.rate = fclk;
425 226
426 /* assume uart clocks are correctly setup */ 227 clkp = init_clocks;
228 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
229 /* ensure that we note the clock state */
427 230
428 /* register our clocks */ 231 clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
429 232
430 if (s3c24xx_register_clock(&clk_xtal) < 0) 233 ret = s3c24xx_register_clock(clkp);
431 printk(KERN_ERR "failed to register master xtal\n"); 234 if (ret < 0) {
235 printk(KERN_ERR "Failed to register clock %s (%d)\n",
236 clkp->name, ret);
237 }
238 }
432 239
433 if (s3c24xx_register_clock(&clk_mpll) < 0) 240 /* We must be careful disabling the clocks we are not intending to
434 printk(KERN_ERR "failed to register mpll clock\n"); 241 * be using at boot time, as subsytems such as the LCD which do
242 * their own DMA requests to the bus can cause the system to lockup
243 * if they where in the middle of requesting bus access.
244 *
245 * Disabling the LCD clock if the LCD is active is very dangerous,
246 * and therefore the bootloader should be careful to not enable
247 * the LCD clock if it is not needed.
248 */
249
250 /* install (and disable) the clocks we do not need immediately */
251
252 clkp = init_clocks_disable;
253 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
254
255 ret = s3c24xx_register_clock(clkp);
256 if (ret < 0) {
257 printk(KERN_ERR "Failed to register clock %s (%d)\n",
258 clkp->name, ret);
259 }
435 260
436 if (s3c24xx_register_clock(&clk_upll) < 0) 261 s3c2410_clkcon_enable(clkp, 0);
437 printk(KERN_ERR "failed to register upll clock\n"); 262 }
438 263
439 if (s3c24xx_register_clock(&clk_f) < 0) 264 /* show the clock-slow value */
440 printk(KERN_ERR "failed to register cpu fclk\n");
441 265
442 if (s3c24xx_register_clock(&clk_h) < 0) 266 xtal = clk_get(NULL, "xtal");
443 printk(KERN_ERR "failed to register cpu hclk\n");
444 267
445 if (s3c24xx_register_clock(&clk_p) < 0) 268 printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
446 printk(KERN_ERR "failed to register cpu pclk\n"); 269 print_mhz(clk_get_rate(xtal) /
270 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
271 (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
272 (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
273 (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
447 274
448 return 0; 275 return 0;
449} 276}
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
deleted file mode 100644
index 7f0ea03e1d49..000000000000
--- a/arch/arm/mach-s3c2410/clock.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 * linux/arch/arm/mach-s3c2410/clock.h
3 *
4 * Copyright (c) 2004-2005 Simtec Electronics
5 * http://www.simtec.co.uk/products/SWLINUX/
6 * Written by Ben Dooks, <ben@simtec.co.uk>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13struct clk {
14 struct list_head list;
15 struct module *owner;
16 struct clk *parent;
17 const char *name;
18 int id;
19 int usage;
20 unsigned long rate;
21 unsigned long ctrlbit;
22
23 int (*enable)(struct clk *, int enable);
24 int (*set_rate)(struct clk *c, unsigned long rate);
25 unsigned long (*get_rate)(struct clk *c);
26 unsigned long (*round_rate)(struct clk *c, unsigned long rate);
27 int (*set_parent)(struct clk *c, struct clk *parent);
28};
29
30/* other clocks which may be registered by board support */
31
32extern struct clk s3c24xx_dclk0;
33extern struct clk s3c24xx_dclk1;
34extern struct clk s3c24xx_clkout0;
35extern struct clk s3c24xx_clkout1;
36extern struct clk s3c24xx_uclk;
37
38extern struct clk clk_usb_bus;
39
40/* core clock support */
41
42extern struct clk clk_f;
43extern struct clk clk_h;
44extern struct clk clk_p;
45extern struct clk clk_mpll;
46extern struct clk clk_upll;
47extern struct clk clk_xtal;
48
49/* exports for arch/arm/mach-s3c2410
50 *
51 * Please DO NOT use these outside of arch/arm/mach-s3c2410
52*/
53
54extern struct mutex clocks_mutex;
55
56extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
57
58extern int s3c24xx_register_clock(struct clk *clk);
59
60extern int s3c24xx_setup_clocks(unsigned long xtal,
61 unsigned long fclk,
62 unsigned long hclk,
63 unsigned long pclk);
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h
deleted file mode 100644
index 0e3a3be330a3..000000000000
--- a/arch/arm/mach-s3c2410/common-smdk.h
+++ /dev/null
@@ -1,15 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/common-smdk.h
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Common code for SMDK2410 and SMDK2440 boards
7 *
8 * http://www.fluff.org/ben/smdk2440/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15extern void smdk_machine_init(void);
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
deleted file mode 100644
index be42e4032a6d..000000000000
--- a/arch/arm/mach-s3c2410/cpu.h
+++ /dev/null
@@ -1,69 +0,0 @@
1/* arch/arm/mach-s3c2410/cpu.h
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for S3C24XX CPU support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13/* todo - fix when rmk changes iodescs to use `void __iomem *` */
14
15#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
16
17#ifndef MHZ
18#define MHZ (1000*1000)
19#endif
20
21#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
22
23/* forward declaration */
24struct s3c24xx_uart_resources;
25struct platform_device;
26struct s3c2410_uartcfg;
27struct map_desc;
28
29/* core initialisation functions */
30
31extern void s3c24xx_init_irq(void);
32
33extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
34
35extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no);
36
37extern void s3c24xx_init_clocks(int xtal);
38
39extern void s3c24xx_init_uartdevs(char *name,
40 struct s3c24xx_uart_resources *res,
41 struct s3c2410_uartcfg *cfg, int no);
42
43/* the board structure is used at first initialsation time
44 * to get info such as the devices to register for this
45 * board. This is done because platfrom_add_devices() cannot
46 * be called from the map_io entry.
47*/
48
49struct s3c24xx_board {
50 struct platform_device **devices;
51 unsigned int devices_count;
52
53 struct clk **clocks;
54 unsigned int clocks_count;
55};
56
57extern void s3c24xx_set_board(struct s3c24xx_board *board);
58
59/* timer for 2410/2440 */
60
61struct sys_timer;
62extern struct sys_timer s3c24xx_timer;
63
64/* system device classes */
65
66extern struct sysdev_class s3c2410_sysclass;
67extern struct sysdev_class s3c2412_sysclass;
68extern struct sysdev_class s3c2440_sysclass;
69extern struct sysdev_class s3c2442_sysclass;
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
deleted file mode 100644
index 14fb0bade716..000000000000
--- a/arch/arm/mach-s3c2410/devs.h
+++ /dev/null
@@ -1,51 +0,0 @@
1/* arch/arm/mach-s3c2410/devs.h
2 *
3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for s3c2410 standard platform devices
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12#include <linux/platform_device.h>
13
14struct s3c24xx_uart_resources {
15 struct resource *resources;
16 unsigned long nr_resources;
17};
18
19extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
20
21extern struct platform_device *s3c24xx_uart_devs[];
22extern struct platform_device *s3c24xx_uart_src[];
23
24extern struct platform_device s3c_device_usb;
25extern struct platform_device s3c_device_lcd;
26extern struct platform_device s3c_device_wdt;
27extern struct platform_device s3c_device_i2c;
28extern struct platform_device s3c_device_iis;
29extern struct platform_device s3c_device_rtc;
30extern struct platform_device s3c_device_adc;
31extern struct platform_device s3c_device_sdi;
32
33extern struct platform_device s3c_device_spi0;
34extern struct platform_device s3c_device_spi1;
35
36extern struct platform_device s3c_device_nand;
37
38extern struct platform_device s3c_device_timer0;
39extern struct platform_device s3c_device_timer1;
40extern struct platform_device s3c_device_timer2;
41extern struct platform_device s3c_device_timer3;
42
43extern struct platform_device s3c_device_usbgadget;
44
45/* s3c2440 specific devices */
46
47#ifdef CONFIG_CPU_S3C2440
48
49extern struct platform_device s3c_device_camif;
50
51#endif
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index fa860e716b4f..67d1ad363973 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -1,9 +1,9 @@
1/* linux/arch/arm/mach-s3c2410/dma.c 1/* linux/arch/arm/mach-s3c2410/dma.c
2 * 2 *
3 * Copyright (c) 2003-2005,2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * S3C2410 DMA core 6 * S3C2410 DMA selection
7 * 7 *
8 * http://armlinux.simtec.co.uk/ 8 * http://armlinux.simtec.co.uk/
9 * 9 *
@@ -12,1430 +12,170 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13*/ 13*/
14 14
15 15#include <linux/kernel.h>
16#ifdef CONFIG_S3C2410_DMA_DEBUG
17#define DEBUG
18#endif
19
20#include <linux/module.h>
21#include <linux/init.h> 16#include <linux/init.h>
22#include <linux/sched.h>
23#include <linux/spinlock.h>
24#include <linux/interrupt.h>
25#include <linux/sysdev.h> 17#include <linux/sysdev.h>
26#include <linux/slab.h> 18#include <linux/serial_core.h>
27#include <linux/errno.h>
28#include <linux/delay.h>
29 19
30#include <asm/system.h>
31#include <asm/irq.h>
32#include <asm/hardware.h>
33#include <asm/io.h>
34#include <asm/dma.h> 20#include <asm/dma.h>
35 21#include <asm/arch/dma.h>
36#include <asm/mach/dma.h> 22
37#include <asm/arch/map.h> 23#include <asm/plat-s3c24xx/cpu.h>
38 24#include <asm/plat-s3c24xx/dma.h>
39#include "dma.h" 25
40 26#include <asm/arch/regs-serial.h>
41/* io map for dma */ 27#include <asm/arch/regs-gpio.h>
42static void __iomem *dma_base; 28#include <asm/arch/regs-ac97.h>
43static struct kmem_cache *dma_kmem; 29#include <asm/arch/regs-mem.h>
44 30#include <asm/arch/regs-lcd.h>
45struct s3c24xx_dma_selection dma_sel; 31#include <asm/arch/regs-sdi.h>
46 32#include <asm/arch/regs-iis.h>
47/* dma channel state information */ 33#include <asm/arch/regs-spi.h>
48struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; 34
49 35static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
50/* debugging functions */ 36 [DMACH_XD0] = {
51 37 .name = "xdreq0",
52#define BUF_MAGIC (0xcafebabe) 38 .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
53 39 },
54#define dmawarn(fmt...) printk(KERN_DEBUG fmt) 40 [DMACH_XD1] = {
55 41 .name = "xdreq1",
56#define dma_regaddr(chan, reg) ((chan)->regs + (reg)) 42 .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
57 43 },
58#if 1 44 [DMACH_SDI] = {
59#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg)) 45 .name = "sdi",
60#else 46 .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
61static inline void 47 .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
62dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val) 48 .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
63{ 49 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
64 pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg); 50 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
65 writel(val, dma_regaddr(chan, reg)); 51 },
66} 52 [DMACH_SPI0] = {
67#endif 53 .name = "spi0",
68 54 .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
69#define dma_rdreg(chan, reg) readl((chan)->regs + (reg)) 55 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
70 56 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
71/* captured register state for debug */ 57 },
72 58 [DMACH_SPI1] = {
73struct s3c2410_dma_regstate { 59 .name = "spi1",
74 unsigned long dcsrc; 60 .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
75 unsigned long disrc; 61 .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
76 unsigned long dstat; 62 .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
77 unsigned long dcon; 63 },
78 unsigned long dmsktrig; 64 [DMACH_UART0] = {
65 .name = "uart0",
66 .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
67 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
68 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
69 },
70 [DMACH_UART1] = {
71 .name = "uart1",
72 .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
73 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
74 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
75 },
76 [DMACH_UART2] = {
77 .name = "uart2",
78 .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
79 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
80 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
81 },
82 [DMACH_TIMER] = {
83 .name = "timer",
84 .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
85 .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
86 .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
87 },
88 [DMACH_I2S_IN] = {
89 .name = "i2s-sdi",
90 .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
91 .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
92 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
93 },
94 [DMACH_I2S_OUT] = {
95 .name = "i2s-sdo",
96 .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
97 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
98 },
99 [DMACH_USB_EP1] = {
100 .name = "usb-ep1",
101 .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
102 },
103 [DMACH_USB_EP2] = {
104 .name = "usb-ep2",
105 .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
106 },
107 [DMACH_USB_EP3] = {
108 .name = "usb-ep3",
109 .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
110 },
111 [DMACH_USB_EP4] = {
112 .name = "usb-ep4",
113 .channels[3] =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
114 },
79}; 115};
80 116
81#ifdef CONFIG_S3C2410_DMA_DEBUG 117static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
82 118 struct s3c24xx_dma_map *map)
83/* dmadbg_showregs
84 *
85 * simple debug routine to print the current state of the dma registers
86*/
87
88static void
89dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
90{
91 regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC);
92 regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC);
93 regs->dstat = dma_rdreg(chan, S3C2410_DMA_DSTAT);
94 regs->dcon = dma_rdreg(chan, S3C2410_DMA_DCON);
95 regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
96}
97
98static void
99dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
100 struct s3c2410_dma_regstate *regs)
101{
102 printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
103 chan->number, fname, line,
104 regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
105 regs->dcon);
106}
107
108static void
109dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
110{
111 struct s3c2410_dma_regstate state;
112
113 dmadbg_capture(chan, &state);
114
115 printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
116 chan->number, fname, line, chan->load_state,
117 chan->curr, chan->next, chan->end);
118
119 dmadbg_dumpregs(fname, line, chan, &state);
120}
121
122static void
123dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
124{
125 struct s3c2410_dma_regstate state;
126
127 dmadbg_capture(chan, &state);
128 dmadbg_dumpregs(fname, line, chan, &state);
129}
130
131#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
132#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
133#else
134#define dbg_showregs(chan) do { } while(0)
135#define dbg_showchan(chan) do { } while(0)
136#endif /* CONFIG_S3C2410_DMA_DEBUG */
137
138static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
139
140/* lookup_dma_channel
141 *
142 * change the dma channel number given into a real dma channel id
143*/
144
145static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
146{
147 if (channel & DMACH_LOW_LEVEL)
148 return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
149 else
150 return dma_chan_map[channel];
151}
152
153/* s3c2410_dma_stats_timeout
154 *
155 * Update DMA stats from timeout info
156*/
157
158static void
159s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
160{ 119{
161 if (stats == NULL) 120 chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
162 return;
163
164 if (val > stats->timeout_longest)
165 stats->timeout_longest = val;
166 if (val < stats->timeout_shortest)
167 stats->timeout_shortest = val;
168
169 stats->timeout_avg += val;
170} 121}
171 122
172/* s3c2410_dma_waitforload 123static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
173 * 124 .select = s3c2410_dma_select,
174 * wait for the DMA engine to load a buffer, and update the state accordingly 125 .dcon_mask = 7 << 24,
175*/ 126 .map = s3c2410_dma_mappings,
176 127 .map_size = ARRAY_SIZE(s3c2410_dma_mappings),
177static int 128};
178s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
179{
180 int timeout = chan->load_timeout;
181 int took;
182
183 if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
184 printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
185 return 0;
186 }
187
188 if (chan->stats != NULL)
189 chan->stats->loads++;
190
191 while (--timeout > 0) {
192 if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
193 took = chan->load_timeout - timeout;
194
195 s3c2410_dma_stats_timeout(chan->stats, took);
196
197 switch (chan->load_state) {
198 case S3C2410_DMALOAD_1LOADED:
199 chan->load_state = S3C2410_DMALOAD_1RUNNING;
200 break;
201
202 default:
203 printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
204 }
205
206 return 1;
207 }
208 }
209
210 if (chan->stats != NULL) {
211 chan->stats->timeout_failed++;
212 }
213
214 return 0;
215}
216
217
218
219/* s3c2410_dma_loadbuffer
220 *
221 * load a buffer, and update the channel state
222*/
223
224static inline int
225s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
226 struct s3c2410_dma_buf *buf)
227{
228 unsigned long reload;
229
230 pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
231 buf, (unsigned long)buf->data, buf->size);
232
233 if (buf == NULL) {
234 dmawarn("buffer is NULL\n");
235 return -EINVAL;
236 }
237
238 /* check the state of the channel before we do anything */
239
240 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
241 dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
242 }
243
244 if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
245 dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
246 }
247
248 /* it would seem sensible if we are the last buffer to not bother
249 * with the auto-reload bit, so that the DMA engine will not try
250 * and load another transfer after this one has finished...
251 */
252 if (chan->load_state == S3C2410_DMALOAD_NONE) {
253 pr_debug("load_state is none, checking for noreload (next=%p)\n",
254 buf->next);
255 reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
256 } else {
257 //pr_debug("load_state is %d => autoreload\n", chan->load_state);
258 reload = S3C2410_DCON_AUTORELOAD;
259 }
260
261 if ((buf->data & 0xf0000000) != 0x30000000) {
262 dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
263 }
264
265 writel(buf->data, chan->addr_reg);
266
267 dma_wrreg(chan, S3C2410_DMA_DCON,
268 chan->dcon | reload | (buf->size/chan->xfer_unit));
269
270 chan->next = buf->next;
271
272 /* update the state of the channel */
273
274 switch (chan->load_state) {
275 case S3C2410_DMALOAD_NONE:
276 chan->load_state = S3C2410_DMALOAD_1LOADED;
277 break;
278
279 case S3C2410_DMALOAD_1RUNNING:
280 chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
281 break;
282
283 default:
284 dmawarn("dmaload: unknown state %d in loadbuffer\n",
285 chan->load_state);
286 break;
287 }
288
289 return 0;
290}
291
292/* s3c2410_dma_call_op
293 *
294 * small routine to call the op routine with the given op if it has been
295 * registered
296*/
297
298static void
299s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
300{
301 if (chan->op_fn != NULL) {
302 (chan->op_fn)(chan, op);
303 }
304}
305
306/* s3c2410_dma_buffdone
307 *
308 * small wrapper to check if callback routine needs to be called, and
309 * if so, call it
310*/
311
312static inline void
313s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
314 enum s3c2410_dma_buffresult result)
315{
316#if 0
317 pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
318 chan->callback_fn, buf, buf->id, buf->size, result);
319#endif
320
321 if (chan->callback_fn != NULL) {
322 (chan->callback_fn)(chan, buf->id, buf->size, result);
323 }
324}
325
326/* s3c2410_dma_start
327 *
328 * start a dma channel going
329*/
330
331static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
332{
333 unsigned long tmp;
334 unsigned long flags;
335
336 pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
337
338 local_irq_save(flags);
339
340 if (chan->state == S3C2410_DMA_RUNNING) {
341 pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
342 local_irq_restore(flags);
343 return 0;
344 }
345
346 chan->state = S3C2410_DMA_RUNNING;
347
348 /* check wether there is anything to load, and if not, see
349 * if we can find anything to load
350 */
351
352 if (chan->load_state == S3C2410_DMALOAD_NONE) {
353 if (chan->next == NULL) {
354 printk(KERN_ERR "dma%d: channel has nothing loaded\n",
355 chan->number);
356 chan->state = S3C2410_DMA_IDLE;
357 local_irq_restore(flags);
358 return -EINVAL;
359 }
360
361 s3c2410_dma_loadbuffer(chan, chan->next);
362 }
363
364 dbg_showchan(chan);
365
366 /* enable the channel */
367
368 if (!chan->irq_enabled) {
369 enable_irq(chan->irq);
370 chan->irq_enabled = 1;
371 }
372
373 /* start the channel going */
374
375 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
376 tmp &= ~S3C2410_DMASKTRIG_STOP;
377 tmp |= S3C2410_DMASKTRIG_ON;
378 dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
379
380 pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
381
382#if 0
383 /* the dma buffer loads should take care of clearing the AUTO
384 * reloading feature */
385 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
386 tmp &= ~S3C2410_DCON_NORELOAD;
387 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
388#endif
389
390 s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
391
392 dbg_showchan(chan);
393
394 /* if we've only loaded one buffer onto the channel, then chec
395 * to see if we have another, and if so, try and load it so when
396 * the first buffer is finished, the new one will be loaded onto
397 * the channel */
398
399 if (chan->next != NULL) {
400 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
401
402 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
403 pr_debug("%s: buff not yet loaded, no more todo\n",
404 __FUNCTION__);
405 } else {
406 chan->load_state = S3C2410_DMALOAD_1RUNNING;
407 s3c2410_dma_loadbuffer(chan, chan->next);
408 }
409
410 } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
411 s3c2410_dma_loadbuffer(chan, chan->next);
412 }
413 }
414
415
416 local_irq_restore(flags);
417
418 return 0;
419}
420
421/* s3c2410_dma_canload
422 *
423 * work out if we can queue another buffer into the DMA engine
424*/
425
426static int
427s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
428{
429 if (chan->load_state == S3C2410_DMALOAD_NONE ||
430 chan->load_state == S3C2410_DMALOAD_1RUNNING)
431 return 1;
432
433 return 0;
434}
435
436/* s3c2410_dma_enqueue
437 *
438 * queue an given buffer for dma transfer.
439 *
440 * id the device driver's id information for this buffer
441 * data the physical address of the buffer data
442 * size the size of the buffer in bytes
443 *
444 * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
445 * is checked, and if set, the channel is started. If this flag isn't set,
446 * then an error will be returned.
447 *
448 * It is possible to queue more than one DMA buffer onto a channel at
449 * once, and the code will deal with the re-loading of the next buffer
450 * when necessary.
451*/
452
453int s3c2410_dma_enqueue(unsigned int channel, void *id,
454 dma_addr_t data, int size)
455{
456 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
457 struct s3c2410_dma_buf *buf;
458 unsigned long flags;
459
460 if (chan == NULL)
461 return -EINVAL;
462
463 pr_debug("%s: id=%p, data=%08x, size=%d\n",
464 __FUNCTION__, id, (unsigned int)data, size);
465
466 buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
467 if (buf == NULL) {
468 pr_debug("%s: out of memory (%ld alloc)\n",
469 __FUNCTION__, (long)sizeof(*buf));
470 return -ENOMEM;
471 }
472
473 //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
474 //dbg_showchan(chan);
475
476 buf->next = NULL;
477 buf->data = buf->ptr = data;
478 buf->size = size;
479 buf->id = id;
480 buf->magic = BUF_MAGIC;
481
482 local_irq_save(flags);
483
484 if (chan->curr == NULL) {
485 /* we've got nothing loaded... */
486 pr_debug("%s: buffer %p queued onto empty channel\n",
487 __FUNCTION__, buf);
488
489 chan->curr = buf;
490 chan->end = buf;
491 chan->next = NULL;
492 } else {
493 pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
494 chan->number, __FUNCTION__, buf);
495
496 if (chan->end == NULL)
497 pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
498 chan->number, __FUNCTION__, chan);
499
500 chan->end->next = buf;
501 chan->end = buf;
502 }
503
504 /* if necessary, update the next buffer field */
505 if (chan->next == NULL)
506 chan->next = buf;
507
508 /* check to see if we can load a buffer */
509 if (chan->state == S3C2410_DMA_RUNNING) {
510 if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
511 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
512 printk(KERN_ERR "dma%d: loadbuffer:"
513 "timeout loading buffer\n",
514 chan->number);
515 dbg_showchan(chan);
516 local_irq_restore(flags);
517 return -EINVAL;
518 }
519 }
520
521 while (s3c2410_dma_canload(chan) && chan->next != NULL) {
522 s3c2410_dma_loadbuffer(chan, chan->next);
523 }
524 } else if (chan->state == S3C2410_DMA_IDLE) {
525 if (chan->flags & S3C2410_DMAF_AUTOSTART) {
526 s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
527 }
528 }
529
530 local_irq_restore(flags);
531 return 0;
532}
533
534EXPORT_SYMBOL(s3c2410_dma_enqueue);
535
536static inline void
537s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
538{
539 int magicok = (buf->magic == BUF_MAGIC);
540
541 buf->magic = -1;
542
543 if (magicok) {
544 kmem_cache_free(dma_kmem, buf);
545 } else {
546 printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
547 }
548}
549
550/* s3c2410_dma_lastxfer
551 *
552 * called when the system is out of buffers, to ensure that the channel
553 * is prepared for shutdown.
554*/
555
556static inline void
557s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
558{
559#if 0
560 pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
561 chan->number, chan->load_state);
562#endif
563
564 switch (chan->load_state) {
565 case S3C2410_DMALOAD_NONE:
566 break;
567
568 case S3C2410_DMALOAD_1LOADED:
569 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
570 /* flag error? */
571 printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
572 chan->number, __FUNCTION__);
573 return;
574 }
575 break;
576
577 case S3C2410_DMALOAD_1LOADED_1RUNNING:
578 /* I belive in this case we do not have anything to do
579 * until the next buffer comes along, and we turn off the
580 * reload */
581 return;
582
583 default:
584 pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
585 chan->number, chan->load_state);
586 return;
587
588 }
589
590 /* hopefully this'll shut the damned thing up after the transfer... */
591 dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
592}
593
594
595#define dmadbg2(x...)
596
597static irqreturn_t
598s3c2410_dma_irq(int irq, void *devpw)
599{
600 struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
601 struct s3c2410_dma_buf *buf;
602
603 buf = chan->curr;
604
605 dbg_showchan(chan);
606
607 /* modify the channel state */
608
609 switch (chan->load_state) {
610 case S3C2410_DMALOAD_1RUNNING:
611 /* TODO - if we are running only one buffer, we probably
612 * want to reload here, and then worry about the buffer
613 * callback */
614
615 chan->load_state = S3C2410_DMALOAD_NONE;
616 break;
617
618 case S3C2410_DMALOAD_1LOADED:
619 /* iirc, we should go back to NONE loaded here, we
620 * had a buffer, and it was never verified as being
621 * loaded.
622 */
623
624 chan->load_state = S3C2410_DMALOAD_NONE;
625 break;
626
627 case S3C2410_DMALOAD_1LOADED_1RUNNING:
628 /* we'll worry about checking to see if another buffer is
629 * ready after we've called back the owner. This should
630 * ensure we do not wait around too long for the DMA
631 * engine to start the next transfer
632 */
633
634 chan->load_state = S3C2410_DMALOAD_1LOADED;
635 break;
636
637 case S3C2410_DMALOAD_NONE:
638 printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
639 chan->number);
640 break;
641
642 default:
643 printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
644 chan->number, chan->load_state);
645 break;
646 }
647
648 if (buf != NULL) {
649 /* update the chain to make sure that if we load any more
650 * buffers when we call the callback function, things should
651 * work properly */
652
653 chan->curr = buf->next;
654 buf->next = NULL;
655
656 if (buf->magic != BUF_MAGIC) {
657 printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
658 chan->number, __FUNCTION__, buf);
659 return IRQ_HANDLED;
660 }
661
662 s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
663
664 /* free resouces */
665 s3c2410_dma_freebuf(buf);
666 } else {
667 }
668
669 /* only reload if the channel is still running... our buffer done
670 * routine may have altered the state by requesting the dma channel
671 * to stop or shutdown... */
672
673 /* todo: check that when the channel is shut-down from inside this
674 * function, we cope with unsetting reload, etc */
675
676 if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
677 unsigned long flags;
678
679 switch (chan->load_state) {
680 case S3C2410_DMALOAD_1RUNNING:
681 /* don't need to do anything for this state */
682 break;
683
684 case S3C2410_DMALOAD_NONE:
685 /* can load buffer immediately */
686 break;
687
688 case S3C2410_DMALOAD_1LOADED:
689 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
690 /* flag error? */
691 printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
692 chan->number, __FUNCTION__);
693 return IRQ_HANDLED;
694 }
695
696 break;
697
698 case S3C2410_DMALOAD_1LOADED_1RUNNING:
699 goto no_load;
700
701 default:
702 printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
703 chan->number, chan->load_state);
704 return IRQ_HANDLED;
705 }
706
707 local_irq_save(flags);
708 s3c2410_dma_loadbuffer(chan, chan->next);
709 local_irq_restore(flags);
710 } else {
711 s3c2410_dma_lastxfer(chan);
712
713 /* see if we can stop this channel.. */
714 if (chan->load_state == S3C2410_DMALOAD_NONE) {
715 pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
716 chan->number, jiffies);
717 s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
718 S3C2410_DMAOP_STOP);
719 }
720 }
721
722 no_load:
723 return IRQ_HANDLED;
724}
725
726static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
727
728/* s3c2410_request_dma
729 *
730 * get control of an dma channel
731*/
732
733int s3c2410_dma_request(unsigned int channel,
734 struct s3c2410_dma_client *client,
735 void *dev)
736{
737 struct s3c2410_dma_chan *chan;
738 unsigned long flags;
739 int err;
740
741 pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
742 channel, client->name, dev);
743
744 local_irq_save(flags);
745
746 chan = s3c2410_dma_map_channel(channel);
747 if (chan == NULL) {
748 local_irq_restore(flags);
749 return -EBUSY;
750 }
751
752 dbg_showchan(chan);
753
754 chan->client = client;
755 chan->in_use = 1;
756
757 if (!chan->irq_claimed) {
758 pr_debug("dma%d: %s : requesting irq %d\n",
759 channel, __FUNCTION__, chan->irq);
760
761 chan->irq_claimed = 1;
762 local_irq_restore(flags);
763
764 err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
765 client->name, (void *)chan);
766
767 local_irq_save(flags);
768
769 if (err) {
770 chan->in_use = 0;
771 chan->irq_claimed = 0;
772 local_irq_restore(flags);
773
774 printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
775 client->name, chan->irq, chan->number);
776 return err;
777 }
778
779 chan->irq_enabled = 1;
780 }
781
782 local_irq_restore(flags);
783
784 /* need to setup */
785
786 pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
787
788 return 0;
789}
790
791EXPORT_SYMBOL(s3c2410_dma_request);
792 129
793/* s3c2410_dma_free 130static struct s3c24xx_dma_order __initdata s3c2410_dma_order = {
794 * 131 .channels = {
795 * release the given channel back to the system, will stop and flush 132 [DMACH_SDI] = {
796 * any outstanding transfers, and ensure the channel is ready for the 133 .list = {
797 * next claimant. 134 [0] = 3 | DMA_CH_VALID,
798 * 135 [1] = 2 | DMA_CH_VALID,
799 * Note, although a warning is currently printed if the freeing client 136 [2] = 0 | DMA_CH_VALID,
800 * info is not the same as the registrant's client info, the free is still 137 },
801 * allowed to go through. 138 },
802*/ 139 [DMACH_I2S_IN] = {
140 .list = {
141 [0] = 1 | DMA_CH_VALID,
142 [1] = 2 | DMA_CH_VALID,
143 },
144 },
145 },
146};
803 147
804int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) 148static int s3c2410_dma_add(struct sys_device *sysdev)
805{ 149{
806 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel); 150 s3c2410_dma_init();
807 unsigned long flags; 151 s3c24xx_dma_order_set(&s3c2410_dma_order);
808 152 return s3c24xx_dma_init_map(&s3c2410_dma_sel);
809 if (chan == NULL)
810 return -EINVAL;
811
812 local_irq_save(flags);
813
814 if (chan->client != client) {
815 printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
816 channel, chan->client, client);
817 }
818
819 /* sort out stopping and freeing the channel */
820
821 if (chan->state != S3C2410_DMA_IDLE) {
822 pr_debug("%s: need to stop dma channel %p\n",
823 __FUNCTION__, chan);
824
825 /* possibly flush the channel */
826 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
827 }
828
829 chan->client = NULL;
830 chan->in_use = 0;
831
832 if (chan->irq_claimed)
833 free_irq(chan->irq, (void *)chan);
834
835 chan->irq_claimed = 0;
836
837 if (!(channel & DMACH_LOW_LEVEL))
838 dma_chan_map[channel] = NULL;
839
840 local_irq_restore(flags);
841
842 return 0;
843} 153}
844 154
845EXPORT_SYMBOL(s3c2410_dma_free); 155#if defined(CONFIG_CPU_S3C2410)
846 156static struct sysdev_driver s3c2410_dma_driver = {
847static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan) 157 .add = s3c2410_dma_add,
848{ 158};
849 unsigned long flags;
850 unsigned long tmp;
851
852 pr_debug("%s:\n", __FUNCTION__);
853
854 dbg_showchan(chan);
855
856 local_irq_save(flags);
857
858 s3c2410_dma_call_op(chan, S3C2410_DMAOP_STOP);
859
860 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
861 tmp |= S3C2410_DMASKTRIG_STOP;
862 //tmp &= ~S3C2410_DMASKTRIG_ON;
863 dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
864
865#if 0
866 /* should also clear interrupts, according to WinCE BSP */
867 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
868 tmp |= S3C2410_DCON_NORELOAD;
869 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
870#endif
871
872 /* should stop do this, or should we wait for flush? */
873 chan->state = S3C2410_DMA_IDLE;
874 chan->load_state = S3C2410_DMALOAD_NONE;
875
876 local_irq_restore(flags);
877
878 return 0;
879}
880 159
881void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan) 160static int __init s3c2410_dma_drvinit(void)
882{ 161{
883 unsigned long tmp; 162 return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
884 unsigned int timeout = 0x10000;
885
886 while (timeout-- > 0) {
887 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
888
889 if (!(tmp & S3C2410_DMASKTRIG_ON))
890 return;
891 }
892
893 pr_debug("dma%d: failed to stop?\n", chan->number);
894} 163}
895 164
896 165arch_initcall(s3c2410_dma_drvinit);
897/* s3c2410_dma_flush
898 *
899 * stop the channel, and remove all current and pending transfers
900*/
901
902static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
903{
904 struct s3c2410_dma_buf *buf, *next;
905 unsigned long flags;
906
907 pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
908
909 dbg_showchan(chan);
910
911 local_irq_save(flags);
912
913 if (chan->state != S3C2410_DMA_IDLE) {
914 pr_debug("%s: stopping channel...\n", __FUNCTION__ );
915 s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
916 }
917
918 buf = chan->curr;
919 if (buf == NULL)
920 buf = chan->next;
921
922 chan->curr = chan->next = chan->end = NULL;
923
924 if (buf != NULL) {
925 for ( ; buf != NULL; buf = next) {
926 next = buf->next;
927
928 pr_debug("%s: free buffer %p, next %p\n",
929 __FUNCTION__, buf, buf->next);
930
931 s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
932 s3c2410_dma_freebuf(buf);
933 }
934 }
935
936 dbg_showregs(chan);
937
938 s3c2410_dma_waitforstop(chan);
939
940#if 0
941 /* should also clear interrupts, according to WinCE BSP */
942 {
943 unsigned long tmp;
944
945 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
946 tmp |= S3C2410_DCON_NORELOAD;
947 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
948 }
949#endif 166#endif
950 167
951 dbg_showregs(chan); 168#if defined(CONFIG_CPU_S3C2442)
952 169/* S3C2442 DMA contains the same selection table as the S3C2410 */
953 local_irq_restore(flags); 170static struct sysdev_driver s3c2442_dma_driver = {
954 171 .add = s3c2410_dma_add,
955 return 0;
956}
957
958int
959s3c2410_dma_started(struct s3c2410_dma_chan *chan)
960{
961 unsigned long flags;
962
963 local_irq_save(flags);
964
965 dbg_showchan(chan);
966
967 /* if we've only loaded one buffer onto the channel, then chec
968 * to see if we have another, and if so, try and load it so when
969 * the first buffer is finished, the new one will be loaded onto
970 * the channel */
971
972 if (chan->next != NULL) {
973 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
974
975 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
976 pr_debug("%s: buff not yet loaded, no more todo\n",
977 __FUNCTION__);
978 } else {
979 chan->load_state = S3C2410_DMALOAD_1RUNNING;
980 s3c2410_dma_loadbuffer(chan, chan->next);
981 }
982
983 } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
984 s3c2410_dma_loadbuffer(chan, chan->next);
985 }
986 }
987
988
989 local_irq_restore(flags);
990
991 return 0;
992
993}
994
995int
996s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
997{
998 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
999
1000 if (chan == NULL)
1001 return -EINVAL;
1002
1003 switch (op) {
1004 case S3C2410_DMAOP_START:
1005 return s3c2410_dma_start(chan);
1006
1007 case S3C2410_DMAOP_STOP:
1008 return s3c2410_dma_dostop(chan);
1009
1010 case S3C2410_DMAOP_PAUSE:
1011 case S3C2410_DMAOP_RESUME:
1012 return -ENOENT;
1013
1014 case S3C2410_DMAOP_FLUSH:
1015 return s3c2410_dma_flush(chan);
1016
1017 case S3C2410_DMAOP_STARTED:
1018 return s3c2410_dma_started(chan);
1019
1020 case S3C2410_DMAOP_TIMEOUT:
1021 return 0;
1022
1023 }
1024
1025 return -ENOENT; /* unknown, don't bother */
1026}
1027
1028EXPORT_SYMBOL(s3c2410_dma_ctrl);
1029
1030/* DMA configuration for each channel
1031 *
1032 * DISRCC -> source of the DMA (AHB,APB)
1033 * DISRC -> source address of the DMA
1034 * DIDSTC -> destination of the DMA (AHB,APD)
1035 * DIDST -> destination address of the DMA
1036*/
1037
1038/* s3c2410_dma_config
1039 *
1040 * xfersize: size of unit in bytes (1,2,4)
1041 * dcon: base value of the DCONx register
1042*/
1043
1044int s3c2410_dma_config(dmach_t channel,
1045 int xferunit,
1046 int dcon)
1047{
1048 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1049
1050 pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
1051 __FUNCTION__, channel, xferunit, dcon);
1052
1053 if (chan == NULL)
1054 return -EINVAL;
1055
1056 pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
1057
1058 dcon |= chan->dcon & dma_sel.dcon_mask;
1059
1060 pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
1061
1062 switch (xferunit) {
1063 case 1:
1064 dcon |= S3C2410_DCON_BYTE;
1065 break;
1066
1067 case 2:
1068 dcon |= S3C2410_DCON_HALFWORD;
1069 break;
1070
1071 case 4:
1072 dcon |= S3C2410_DCON_WORD;
1073 break;
1074
1075 default:
1076 pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
1077 return -EINVAL;
1078 }
1079
1080 dcon |= S3C2410_DCON_HWTRIG;
1081 dcon |= S3C2410_DCON_INTREQ;
1082
1083 pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
1084
1085 chan->dcon = dcon;
1086 chan->xfer_unit = xferunit;
1087
1088 return 0;
1089}
1090
1091EXPORT_SYMBOL(s3c2410_dma_config);
1092
1093int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
1094{
1095 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1096
1097 if (chan == NULL)
1098 return -EINVAL;
1099
1100 pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
1101
1102 chan->flags = flags;
1103
1104 return 0;
1105}
1106
1107EXPORT_SYMBOL(s3c2410_dma_setflags);
1108
1109
1110/* do we need to protect the settings of the fields from
1111 * irq?
1112*/
1113
1114int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
1115{
1116 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1117
1118 if (chan == NULL)
1119 return -EINVAL;
1120
1121 pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
1122
1123 chan->op_fn = rtn;
1124
1125 return 0;
1126}
1127
1128EXPORT_SYMBOL(s3c2410_dma_set_opfn);
1129
1130int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
1131{
1132 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1133
1134 if (chan == NULL)
1135 return -EINVAL;
1136
1137 pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
1138
1139 chan->callback_fn = rtn;
1140
1141 return 0;
1142}
1143
1144EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
1145
1146/* s3c2410_dma_devconfig
1147 *
1148 * configure the dma source/destination hardware type and address
1149 *
1150 * source: S3C2410_DMASRC_HW: source is hardware
1151 * S3C2410_DMASRC_MEM: source is memory
1152 *
1153 * hwcfg: the value for xxxSTCn register,
1154 * bit 0: 0=increment pointer, 1=leave pointer
1155 * bit 1: 0=soucre is AHB, 1=soucre is APB
1156 *
1157 * devaddr: physical address of the source
1158*/
1159
1160int s3c2410_dma_devconfig(int channel,
1161 enum s3c2410_dmasrc source,
1162 int hwcfg,
1163 unsigned long devaddr)
1164{
1165 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1166
1167 if (chan == NULL)
1168 return -EINVAL;
1169
1170 pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
1171 __FUNCTION__, (int)source, hwcfg, devaddr);
1172
1173 chan->source = source;
1174 chan->dev_addr = devaddr;
1175
1176 switch (source) {
1177 case S3C2410_DMASRC_HW:
1178 /* source is hardware */
1179 pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
1180 __FUNCTION__, devaddr, hwcfg);
1181 dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
1182 dma_wrreg(chan, S3C2410_DMA_DISRC, devaddr);
1183 dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
1184
1185 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
1186 return 0;
1187
1188 case S3C2410_DMASRC_MEM:
1189 /* source is memory */
1190 pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
1191 __FUNCTION__, devaddr, hwcfg);
1192 dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
1193 dma_wrreg(chan, S3C2410_DMA_DIDST, devaddr);
1194 dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
1195
1196 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
1197 return 0;
1198 }
1199
1200 printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
1201 return -EINVAL;
1202}
1203
1204EXPORT_SYMBOL(s3c2410_dma_devconfig);
1205
1206/* s3c2410_dma_getposition
1207 *
1208 * returns the current transfer points for the dma source and destination
1209*/
1210
1211int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
1212{
1213 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1214
1215 if (chan == NULL)
1216 return -EINVAL;
1217
1218 if (src != NULL)
1219 *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
1220
1221 if (dst != NULL)
1222 *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
1223
1224 return 0;
1225}
1226
1227EXPORT_SYMBOL(s3c2410_dma_getposition);
1228
1229
1230/* system device class */
1231
1232#ifdef CONFIG_PM
1233
1234static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
1235{
1236 struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
1237
1238 printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
1239
1240 if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
1241 /* the dma channel is still working, which is probably
1242 * a bad thing to do over suspend/resume. We stop the
1243 * channel and assume that the client is either going to
1244 * retry after resume, or that it is broken.
1245 */
1246
1247 printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
1248 cp->number);
1249
1250 s3c2410_dma_dostop(cp);
1251 }
1252
1253 return 0;
1254}
1255
1256static int s3c2410_dma_resume(struct sys_device *dev)
1257{
1258 return 0;
1259}
1260
1261#else
1262#define s3c2410_dma_suspend NULL
1263#define s3c2410_dma_resume NULL
1264#endif /* CONFIG_PM */
1265
1266struct sysdev_class dma_sysclass = {
1267 set_kset_name("s3c24xx-dma"),
1268 .suspend = s3c2410_dma_suspend,
1269 .resume = s3c2410_dma_resume,
1270}; 172};
1271 173
1272/* kmem cache implementation */ 174static int __init s3c2442_dma_drvinit(void)
1273
1274static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
1275{
1276 memset(p, 0, sizeof(struct s3c2410_dma_buf));
1277}
1278
1279/* initialisation code */
1280
1281static int __init s3c2410_init_dma(void)
1282{
1283 struct s3c2410_dma_chan *cp;
1284 int channel;
1285 int ret;
1286
1287 printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
1288
1289 dma_base = ioremap(S3C24XX_PA_DMA, 0x200);
1290 if (dma_base == NULL) {
1291 printk(KERN_ERR "dma failed to remap register block\n");
1292 return -ENOMEM;
1293 }
1294
1295 printk("Registering sysclass\n");
1296
1297 ret = sysdev_class_register(&dma_sysclass);
1298 if (ret != 0) {
1299 printk(KERN_ERR "dma sysclass registration failed\n");
1300 goto err;
1301 }
1302
1303 dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
1304 SLAB_HWCACHE_ALIGN,
1305 s3c2410_dma_cache_ctor, NULL);
1306
1307 if (dma_kmem == NULL) {
1308 printk(KERN_ERR "dma failed to make kmem cache\n");
1309 ret = -ENOMEM;
1310 goto err;
1311 }
1312
1313 for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
1314 cp = &s3c2410_chans[channel];
1315
1316 memset(cp, 0, sizeof(struct s3c2410_dma_chan));
1317
1318 /* dma channel irqs are in order.. */
1319 cp->number = channel;
1320 cp->irq = channel + IRQ_DMA0;
1321 cp->regs = dma_base + (channel*0x40);
1322
1323 /* point current stats somewhere */
1324 cp->stats = &cp->stats_store;
1325 cp->stats_store.timeout_shortest = LONG_MAX;
1326
1327 /* basic channel configuration */
1328
1329 cp->load_timeout = 1<<18;
1330
1331 /* register system device */
1332
1333 cp->dev.cls = &dma_sysclass;
1334 cp->dev.id = channel;
1335 ret = sysdev_register(&cp->dev);
1336
1337 printk("DMA channel %d at %p, irq %d\n",
1338 cp->number, cp->regs, cp->irq);
1339 }
1340
1341 return 0;
1342
1343 err:
1344 kmem_cache_destroy(dma_kmem);
1345 iounmap(dma_base);
1346 dma_base = NULL;
1347 return ret;
1348}
1349
1350core_initcall(s3c2410_init_dma);
1351
1352static inline int is_channel_valid(unsigned int channel)
1353{ 175{
1354 return (channel & DMA_CH_VALID); 176 return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
1355} 177}
1356 178
1357/* s3c2410_dma_map_channel() 179arch_initcall(s3c2442_dma_drvinit);
1358 * 180#endif
1359 * turn the virtual channel number into a real, and un-used hardware
1360 * channel.
1361 *
1362 * currently this code uses first-free channel from the specified harware
1363 * map, not taking into account anything that the board setup code may
1364 * have to say about the likely peripheral set to be in use.
1365*/
1366
1367struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
1368{
1369 struct s3c24xx_dma_map *ch_map;
1370 struct s3c2410_dma_chan *dmach;
1371 int ch;
1372
1373 if (dma_sel.map == NULL || channel > dma_sel.map_size)
1374 return NULL;
1375
1376 ch_map = dma_sel.map + channel;
1377
1378 for (ch = 0; ch < S3C2410_DMA_CHANNELS; ch++) {
1379 if (!is_channel_valid(ch_map->channels[ch]))
1380 continue;
1381
1382 if (s3c2410_chans[ch].in_use == 0) {
1383 printk("mapped channel %d to %d\n", channel, ch);
1384 break;
1385 }
1386 }
1387
1388 if (ch >= S3C2410_DMA_CHANNELS)
1389 return NULL;
1390
1391 /* update our channel mapping */
1392
1393 dmach = &s3c2410_chans[ch];
1394 dma_chan_map[channel] = dmach;
1395
1396 /* select the channel */
1397
1398 (dma_sel.select)(dmach, ch_map);
1399
1400 return dmach;
1401}
1402
1403static void s3c24xx_dma_show_ch(struct s3c24xx_dma_map *map, int ch)
1404{
1405 /* show the channel configuration */
1406
1407 printk("%2d: %20s, channels %c%c%c%c\n", ch, map->name,
1408 (is_channel_valid(map->channels[0]) ? '0' : '-'),
1409 (is_channel_valid(map->channels[1]) ? '1' : '-'),
1410 (is_channel_valid(map->channels[2]) ? '2' : '-'),
1411 (is_channel_valid(map->channels[3]) ? '3' : '-'));
1412}
1413
1414static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
1415{
1416 if (1)
1417 s3c24xx_dma_show_ch(map, ch);
1418
1419 return 0;
1420}
1421
1422int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
1423{
1424 struct s3c24xx_dma_map *nmap;
1425 size_t map_sz = sizeof(*nmap) * sel->map_size;
1426 int ptr;
1427
1428 nmap = kmalloc(map_sz, GFP_KERNEL);
1429 if (nmap == NULL)
1430 return -ENOMEM;
1431
1432 memcpy(nmap, sel->map, map_sz);
1433 memcpy(&dma_sel, sel, sizeof(*sel));
1434
1435 dma_sel.map = nmap;
1436
1437 for (ptr = 0; ptr < sel->map_size; ptr++)
1438 s3c24xx_dma_check_entry(nmap+ptr, ptr);
1439 181
1440 return 0;
1441}
diff --git a/arch/arm/mach-s3c2410/dma.h b/arch/arm/mach-s3c2410/dma.h
deleted file mode 100644
index 0ebfe0aab80b..000000000000
--- a/arch/arm/mach-s3c2410/dma.h
+++ /dev/null
@@ -1,45 +0,0 @@
1/* arch/arm/mach-s3c2410/dma.h
2 *
3 * Copyright (C) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Samsung S3C24XX DMA support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13extern struct sysdev_class dma_sysclass;
14extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
15
16#define DMA_CH_VALID (1<<31)
17
18struct s3c24xx_dma_addr {
19 unsigned long from;
20 unsigned long to;
21};
22
23/* struct s3c24xx_dma_map
24 *
25 * this holds the mapping information for the channel selected
26 * to be connected to the specified device
27*/
28
29struct s3c24xx_dma_map {
30 const char *name;
31 struct s3c24xx_dma_addr hw_addr;
32
33 unsigned long channels[S3C2410_DMA_CHANNELS];
34};
35
36struct s3c24xx_dma_selection {
37 struct s3c24xx_dma_map *map;
38 unsigned long map_size;
39 unsigned long dcon_mask;
40
41 void (*select)(struct s3c2410_dma_chan *chan,
42 struct s3c24xx_dma_map *map);
43};
44
45extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index f6fb215bb48c..01e795d1146e 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -1,9 +1,9 @@
1/* linux/arch/arm/mach-s3c2410/gpio.c 1/* linux/arch/arm/mach-s3c2410/gpio.c
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2004-2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * S3C24XX GPIO support 6 * S3C2410 GPIO support
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -18,8 +18,7 @@
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/ 21 */
22
23 22
24#include <linux/kernel.h> 23#include <linux/kernel.h>
25#include <linux/init.h> 24#include <linux/init.h>
@@ -33,156 +32,40 @@
33 32
34#include <asm/arch/regs-gpio.h> 33#include <asm/arch/regs-gpio.h>
35 34
36void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) 35int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
37{ 36 unsigned int config)
38 void __iomem *base = S3C24XX_GPIO_BASE(pin);
39 unsigned long mask;
40 unsigned long con;
41 unsigned long flags;
42
43 if (pin < S3C2410_GPIO_BANKB) {
44 mask = 1 << S3C2410_GPIO_OFFSET(pin);
45 } else {
46 mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
47 }
48
49 switch (function) {
50 case S3C2410_GPIO_LEAVE:
51 mask = 0;
52 function = 0;
53 break;
54
55 case S3C2410_GPIO_INPUT:
56 case S3C2410_GPIO_OUTPUT:
57 case S3C2410_GPIO_SFN2:
58 case S3C2410_GPIO_SFN3:
59 if (pin < S3C2410_GPIO_BANKB) {
60 function -= 1;
61 function &= 1;
62 function <<= S3C2410_GPIO_OFFSET(pin);
63 } else {
64 function &= 3;
65 function <<= S3C2410_GPIO_OFFSET(pin)*2;
66 }
67 }
68
69 /* modify the specified register wwith IRQs off */
70
71 local_irq_save(flags);
72
73 con = __raw_readl(base + 0x00);
74 con &= ~mask;
75 con |= function;
76
77 __raw_writel(con, base + 0x00);
78
79 local_irq_restore(flags);
80}
81
82EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
83
84unsigned int s3c2410_gpio_getcfg(unsigned int pin)
85{
86 void __iomem *base = S3C24XX_GPIO_BASE(pin);
87 unsigned long val = __raw_readl(base);
88
89 if (pin < S3C2410_GPIO_BANKB) {
90 val >>= S3C2410_GPIO_OFFSET(pin);
91 val &= 1;
92 val += 1;
93 } else {
94 val >>= S3C2410_GPIO_OFFSET(pin)*2;
95 val &= 3;
96 }
97
98 return val | S3C2410_GPIO_INPUT;
99}
100
101EXPORT_SYMBOL(s3c2410_gpio_getcfg);
102
103void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
104{ 37{
105 void __iomem *base = S3C24XX_GPIO_BASE(pin); 38 void __iomem *reg = S3C24XX_EINFLT0;
106 unsigned long offs = S3C2410_GPIO_OFFSET(pin);
107 unsigned long flags; 39 unsigned long flags;
108 unsigned long up; 40 unsigned long val;
109
110 if (pin < S3C2410_GPIO_BANKB)
111 return;
112
113 local_irq_save(flags);
114
115 up = __raw_readl(base + 0x08);
116 up &= ~(1L << offs);
117 up |= to << offs;
118 __raw_writel(up, base + 0x08);
119 41
120 local_irq_restore(flags); 42 if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
121} 43 return -1;
122 44
123EXPORT_SYMBOL(s3c2410_gpio_pullup); 45 config &= 0xff;
124 46
125void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) 47 pin -= S3C2410_GPG8;
126{ 48 reg += pin & ~3;
127 void __iomem *base = S3C24XX_GPIO_BASE(pin);
128 unsigned long offs = S3C2410_GPIO_OFFSET(pin);
129 unsigned long flags;
130 unsigned long dat;
131 49
132 local_irq_save(flags); 50 local_irq_save(flags);
133 51
134 dat = __raw_readl(base + 0x04); 52 /* update filter width and clock source */
135 dat &= ~(1 << offs);
136 dat |= to << offs;
137 __raw_writel(dat, base + 0x04);
138
139 local_irq_restore(flags);
140}
141
142EXPORT_SYMBOL(s3c2410_gpio_setpin);
143
144unsigned int s3c2410_gpio_getpin(unsigned int pin)
145{
146 void __iomem *base = S3C24XX_GPIO_BASE(pin);
147 unsigned long offs = S3C2410_GPIO_OFFSET(pin);
148 53
149 return __raw_readl(base + 0x04) & (1<< offs); 54 val = __raw_readl(reg);
150} 55 val &= ~(0xff << ((pin & 3) * 8));
56 val |= config << ((pin & 3) * 8);
57 __raw_writel(val, reg);
151 58
152EXPORT_SYMBOL(s3c2410_gpio_getpin); 59 /* update filter enable */
153 60
154unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) 61 val = __raw_readl(S3C24XX_EXTINT2);
155{ 62 val &= ~(1 << ((pin * 4) + 3));
156 unsigned long flags; 63 val |= on << ((pin * 4) + 3);
157 unsigned long misccr; 64 __raw_writel(val, S3C24XX_EXTINT2);
158 65
159 local_irq_save(flags);
160 misccr = __raw_readl(S3C24XX_MISCCR);
161 misccr &= ~clear;
162 misccr ^= change;
163 __raw_writel(misccr, S3C24XX_MISCCR);
164 local_irq_restore(flags); 66 local_irq_restore(flags);
165 67
166 return misccr; 68 return 0;
167}
168
169EXPORT_SYMBOL(s3c2410_modify_misccr);
170
171int s3c2410_gpio_getirq(unsigned int pin)
172{
173 if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
174 return -1; /* not valid interrupts */
175
176 if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
177 return -1; /* not valid pin */
178
179 if (pin < S3C2410_GPF4)
180 return (pin - S3C2410_GPF0) + IRQ_EINT0;
181
182 if (pin < S3C2410_GPG0)
183 return (pin - S3C2410_GPF4) + IRQ_EINT4;
184
185 return (pin - S3C2410_GPG0) + IRQ_EINT8;
186} 69}
187 70
188EXPORT_SYMBOL(s3c2410_gpio_getirq); 71EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 3c0ed7871c55..53cbdaa43ac6 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -1,6 +1,6 @@
1/* linux/arch/arm/mach-s3c2410/irq.c 1/* linux/arch/arm/mach-s3c2410/irq.c
2 * 2 *
3 * Copyright (c) 2003,2004 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
@@ -17,37 +17,6 @@
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * 19 *
20 * Changelog:
21 *
22 * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
23 * Fixed compile warnings
24 *
25 * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
26 * Fixed s3c_extirq_type
27 *
28 * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
29 * Addition of ADC/TC demux
30 *
31 * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de>
32 * Fix for set_irq_type() on low EINT numbers
33 *
34 * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
35 * Tidy up KF's patch and sort out new release
36 *
37 * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
38 * Add support for power management controls
39 *
40 * 04-Nov-2004 Ben Dooks
41 * Fix standard IRQ wake for EINT0..4 and RTC
42 *
43 * 22-Feb-2005 Ben Dooks
44 * Fixed edge-triggering on ADC IRQ
45 *
46 * 28-Jun-2005 Ben Dooks
47 * Mark IRQ_LCD valid
48 *
49 * 25-Jul-2005 Ben Dooks
50 * Split the S3C2440 IRQ code to seperate file
51*/ 20*/
52 21
53#include <linux/init.h> 22#include <linux/init.h>
@@ -57,745 +26,23 @@
57#include <linux/ptrace.h> 26#include <linux/ptrace.h>
58#include <linux/sysdev.h> 27#include <linux/sysdev.h>
59 28
60#include <asm/hardware.h> 29#include <asm/plat-s3c24xx/cpu.h>
61#include <asm/irq.h> 30#include <asm/plat-s3c24xx/pm.h>
62#include <asm/io.h>
63
64#include <asm/mach/irq.h>
65
66#include <asm/arch/regs-irq.h>
67#include <asm/arch/regs-gpio.h>
68
69#include "cpu.h"
70#include "pm.h"
71#include "irq.h"
72
73/* wakeup irq control */
74
75#ifdef CONFIG_PM
76
77/* state for IRQs over sleep */
78
79/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
80 *
81 * set bit to 1 in allow bitfield to enable the wakeup settings on it
82*/
83
84unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
85unsigned long s3c_irqwake_intmask = 0xffffffffL;
86unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
87unsigned long s3c_irqwake_eintmask = 0xffffffffL;
88
89int
90s3c_irq_wake(unsigned int irqno, unsigned int state)
91{
92 unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
93
94 if (!(s3c_irqwake_intallow & irqbit))
95 return -ENOENT;
96
97 printk(KERN_INFO "wake %s for irq %d\n",
98 state ? "enabled" : "disabled", irqno);
99
100 if (!state)
101 s3c_irqwake_intmask |= irqbit;
102 else
103 s3c_irqwake_intmask &= ~irqbit;
104
105 return 0;
106}
107
108static int
109s3c_irqext_wake(unsigned int irqno, unsigned int state)
110{
111 unsigned long bit = 1L << (irqno - EXTINT_OFF);
112
113 if (!(s3c_irqwake_eintallow & bit))
114 return -ENOENT;
115
116 printk(KERN_INFO "wake %s for irq %d\n",
117 state ? "enabled" : "disabled", irqno);
118
119 if (!state)
120 s3c_irqwake_eintmask |= bit;
121 else
122 s3c_irqwake_eintmask &= ~bit;
123
124 return 0;
125}
126
127#else
128#define s3c_irqext_wake NULL
129#define s3c_irq_wake NULL
130#endif
131
132
133static void
134s3c_irq_mask(unsigned int irqno)
135{
136 unsigned long mask;
137
138 irqno -= IRQ_EINT0;
139
140 mask = __raw_readl(S3C2410_INTMSK);
141 mask |= 1UL << irqno;
142 __raw_writel(mask, S3C2410_INTMSK);
143}
144
145static inline void
146s3c_irq_ack(unsigned int irqno)
147{
148 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
149
150 __raw_writel(bitval, S3C2410_SRCPND);
151 __raw_writel(bitval, S3C2410_INTPND);
152}
153
154static inline void
155s3c_irq_maskack(unsigned int irqno)
156{
157 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
158 unsigned long mask;
159
160 mask = __raw_readl(S3C2410_INTMSK);
161 __raw_writel(mask|bitval, S3C2410_INTMSK);
162
163 __raw_writel(bitval, S3C2410_SRCPND);
164 __raw_writel(bitval, S3C2410_INTPND);
165}
166
167
168static void
169s3c_irq_unmask(unsigned int irqno)
170{
171 unsigned long mask;
172
173 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
174 irqdbf2("s3c_irq_unmask %d\n", irqno);
175
176 irqno -= IRQ_EINT0;
177
178 mask = __raw_readl(S3C2410_INTMSK);
179 mask &= ~(1UL << irqno);
180 __raw_writel(mask, S3C2410_INTMSK);
181}
182
183struct irq_chip s3c_irq_level_chip = {
184 .name = "s3c-level",
185 .ack = s3c_irq_maskack,
186 .mask = s3c_irq_mask,
187 .unmask = s3c_irq_unmask,
188 .set_wake = s3c_irq_wake
189};
190
191static struct irq_chip s3c_irq_chip = {
192 .name = "s3c",
193 .ack = s3c_irq_ack,
194 .mask = s3c_irq_mask,
195 .unmask = s3c_irq_unmask,
196 .set_wake = s3c_irq_wake
197};
198
199static void
200s3c_irqext_mask(unsigned int irqno)
201{
202 unsigned long mask;
203
204 irqno -= EXTINT_OFF;
205
206 mask = __raw_readl(S3C24XX_EINTMASK);
207 mask |= ( 1UL << irqno);
208 __raw_writel(mask, S3C24XX_EINTMASK);
209}
210
211static void
212s3c_irqext_ack(unsigned int irqno)
213{
214 unsigned long req;
215 unsigned long bit;
216 unsigned long mask;
217 31
218 bit = 1UL << (irqno - EXTINT_OFF); 32static int s3c2410_irq_add(struct sys_device *sysdev)
219
220 mask = __raw_readl(S3C24XX_EINTMASK);
221
222 __raw_writel(bit, S3C24XX_EINTPEND);
223
224 req = __raw_readl(S3C24XX_EINTPEND);
225 req &= ~mask;
226
227 /* not sure if we should be acking the parent irq... */
228
229 if (irqno <= IRQ_EINT7 ) {
230 if ((req & 0xf0) == 0)
231 s3c_irq_ack(IRQ_EINT4t7);
232 } else {
233 if ((req >> 8) == 0)
234 s3c_irq_ack(IRQ_EINT8t23);
235 }
236}
237
238static void
239s3c_irqext_unmask(unsigned int irqno)
240{ 33{
241 unsigned long mask;
242
243 irqno -= EXTINT_OFF;
244
245 mask = __raw_readl(S3C24XX_EINTMASK);
246 mask &= ~( 1UL << irqno);
247 __raw_writel(mask, S3C24XX_EINTMASK);
248}
249
250int
251s3c_irqext_type(unsigned int irq, unsigned int type)
252{
253 void __iomem *extint_reg;
254 void __iomem *gpcon_reg;
255 unsigned long gpcon_offset, extint_offset;
256 unsigned long newvalue = 0, value;
257
258 if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
259 {
260 gpcon_reg = S3C2410_GPFCON;
261 extint_reg = S3C24XX_EXTINT0;
262 gpcon_offset = (irq - IRQ_EINT0) * 2;
263 extint_offset = (irq - IRQ_EINT0) * 4;
264 }
265 else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
266 {
267 gpcon_reg = S3C2410_GPFCON;
268 extint_reg = S3C24XX_EXTINT0;
269 gpcon_offset = (irq - (EXTINT_OFF)) * 2;
270 extint_offset = (irq - (EXTINT_OFF)) * 4;
271 }
272 else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
273 {
274 gpcon_reg = S3C2410_GPGCON;
275 extint_reg = S3C24XX_EXTINT1;
276 gpcon_offset = (irq - IRQ_EINT8) * 2;
277 extint_offset = (irq - IRQ_EINT8) * 4;
278 }
279 else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
280 {
281 gpcon_reg = S3C2410_GPGCON;
282 extint_reg = S3C24XX_EXTINT2;
283 gpcon_offset = (irq - IRQ_EINT8) * 2;
284 extint_offset = (irq - IRQ_EINT16) * 4;
285 } else
286 return -1;
287
288 /* Set the GPIO to external interrupt mode */
289 value = __raw_readl(gpcon_reg);
290 value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
291 __raw_writel(value, gpcon_reg);
292
293 /* Set the external interrupt to pointed trigger type */
294 switch (type)
295 {
296 case IRQT_NOEDGE:
297 printk(KERN_WARNING "No edge setting!\n");
298 break;
299
300 case IRQT_RISING:
301 newvalue = S3C2410_EXTINT_RISEEDGE;
302 break;
303
304 case IRQT_FALLING:
305 newvalue = S3C2410_EXTINT_FALLEDGE;
306 break;
307
308 case IRQT_BOTHEDGE:
309 newvalue = S3C2410_EXTINT_BOTHEDGE;
310 break;
311
312 case IRQT_LOW:
313 newvalue = S3C2410_EXTINT_LOWLEV;
314 break;
315
316 case IRQT_HIGH:
317 newvalue = S3C2410_EXTINT_HILEV;
318 break;
319
320 default:
321 printk(KERN_ERR "No such irq type %d", type);
322 return -1;
323 }
324
325 value = __raw_readl(extint_reg);
326 value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
327 __raw_writel(value, extint_reg);
328
329 return 0; 34 return 0;
330} 35}
331 36
332static struct irq_chip s3c_irqext_chip = { 37static struct sysdev_driver s3c2410_irq_driver = {
333 .name = "s3c-ext", 38 .add = s3c2410_irq_add,
334 .mask = s3c_irqext_mask, 39 .suspend = s3c24xx_irq_suspend,
335 .unmask = s3c_irqext_unmask, 40 .resume = s3c24xx_irq_resume,
336 .ack = s3c_irqext_ack,
337 .set_type = s3c_irqext_type,
338 .set_wake = s3c_irqext_wake
339};
340
341static struct irq_chip s3c_irq_eint0t4 = {
342 .name = "s3c-ext0",
343 .ack = s3c_irq_ack,
344 .mask = s3c_irq_mask,
345 .unmask = s3c_irq_unmask,
346 .set_wake = s3c_irq_wake,
347 .set_type = s3c_irqext_type,
348};
349
350/* mask values for the parent registers for each of the interrupt types */
351
352#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0))
353#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
354#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
355#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
356
357
358/* UART0 */
359
360static void
361s3c_irq_uart0_mask(unsigned int irqno)
362{
363 s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
364}
365
366static void
367s3c_irq_uart0_unmask(unsigned int irqno)
368{
369 s3c_irqsub_unmask(irqno, INTMSK_UART0);
370}
371
372static void
373s3c_irq_uart0_ack(unsigned int irqno)
374{
375 s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
376}
377
378static struct irq_chip s3c_irq_uart0 = {
379 .name = "s3c-uart0",
380 .mask = s3c_irq_uart0_mask,
381 .unmask = s3c_irq_uart0_unmask,
382 .ack = s3c_irq_uart0_ack,
383};
384
385/* UART1 */
386
387static void
388s3c_irq_uart1_mask(unsigned int irqno)
389{
390 s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
391}
392
393static void
394s3c_irq_uart1_unmask(unsigned int irqno)
395{
396 s3c_irqsub_unmask(irqno, INTMSK_UART1);
397}
398
399static void
400s3c_irq_uart1_ack(unsigned int irqno)
401{
402 s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
403}
404
405static struct irq_chip s3c_irq_uart1 = {
406 .name = "s3c-uart1",
407 .mask = s3c_irq_uart1_mask,
408 .unmask = s3c_irq_uart1_unmask,
409 .ack = s3c_irq_uart1_ack,
410};
411
412/* UART2 */
413
414static void
415s3c_irq_uart2_mask(unsigned int irqno)
416{
417 s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
418}
419
420static void
421s3c_irq_uart2_unmask(unsigned int irqno)
422{
423 s3c_irqsub_unmask(irqno, INTMSK_UART2);
424}
425
426static void
427s3c_irq_uart2_ack(unsigned int irqno)
428{
429 s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
430}
431
432static struct irq_chip s3c_irq_uart2 = {
433 .name = "s3c-uart2",
434 .mask = s3c_irq_uart2_mask,
435 .unmask = s3c_irq_uart2_unmask,
436 .ack = s3c_irq_uart2_ack,
437};
438
439/* ADC and Touchscreen */
440
441static void
442s3c_irq_adc_mask(unsigned int irqno)
443{
444 s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
445}
446
447static void
448s3c_irq_adc_unmask(unsigned int irqno)
449{
450 s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
451}
452
453static void
454s3c_irq_adc_ack(unsigned int irqno)
455{
456 s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
457}
458
459static struct irq_chip s3c_irq_adc = {
460 .name = "s3c-adc",
461 .mask = s3c_irq_adc_mask,
462 .unmask = s3c_irq_adc_unmask,
463 .ack = s3c_irq_adc_ack,
464};
465
466/* irq demux for adc */
467static void s3c_irq_demux_adc(unsigned int irq,
468 struct irq_desc *desc)
469{
470 unsigned int subsrc, submsk;
471 unsigned int offset = 9;
472 struct irq_desc *mydesc;
473
474 /* read the current pending interrupts, and the mask
475 * for what it is available */
476
477 subsrc = __raw_readl(S3C2410_SUBSRCPND);
478 submsk = __raw_readl(S3C2410_INTSUBMSK);
479
480 subsrc &= ~submsk;
481 subsrc >>= offset;
482 subsrc &= 3;
483
484 if (subsrc != 0) {
485 if (subsrc & 1) {
486 mydesc = irq_desc + IRQ_TC;
487 desc_handle_irq(IRQ_TC, mydesc);
488 }
489 if (subsrc & 2) {
490 mydesc = irq_desc + IRQ_ADC;
491 desc_handle_irq(IRQ_ADC, mydesc);
492 }
493 }
494}
495
496static void s3c_irq_demux_uart(unsigned int start)
497{
498 unsigned int subsrc, submsk;
499 unsigned int offset = start - IRQ_S3CUART_RX0;
500 struct irq_desc *desc;
501
502 /* read the current pending interrupts, and the mask
503 * for what it is available */
504
505 subsrc = __raw_readl(S3C2410_SUBSRCPND);
506 submsk = __raw_readl(S3C2410_INTSUBMSK);
507
508 irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
509 start, offset, subsrc, submsk);
510
511 subsrc &= ~submsk;
512 subsrc >>= offset;
513 subsrc &= 7;
514
515 if (subsrc != 0) {
516 desc = irq_desc + start;
517
518 if (subsrc & 1)
519 desc_handle_irq(start, desc);
520
521 desc++;
522
523 if (subsrc & 2)
524 desc_handle_irq(start+1, desc);
525
526 desc++;
527
528 if (subsrc & 4)
529 desc_handle_irq(start+2, desc);
530 }
531}
532
533/* uart demux entry points */
534
535static void
536s3c_irq_demux_uart0(unsigned int irq,
537 struct irq_desc *desc)
538{
539 irq = irq;
540 s3c_irq_demux_uart(IRQ_S3CUART_RX0);
541}
542
543static void
544s3c_irq_demux_uart1(unsigned int irq,
545 struct irq_desc *desc)
546{
547 irq = irq;
548 s3c_irq_demux_uart(IRQ_S3CUART_RX1);
549}
550
551static void
552s3c_irq_demux_uart2(unsigned int irq,
553 struct irq_desc *desc)
554{
555 irq = irq;
556 s3c_irq_demux_uart(IRQ_S3CUART_RX2);
557}
558
559static void
560s3c_irq_demux_extint8(unsigned int irq,
561 struct irq_desc *desc)
562{
563 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
564 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
565
566 eintpnd &= ~eintmsk;
567 eintpnd &= ~0xff; /* ignore lower irqs */
568
569 /* we may as well handle all the pending IRQs here */
570
571 while (eintpnd) {
572 irq = __ffs(eintpnd);
573 eintpnd &= ~(1<<irq);
574
575 irq += (IRQ_EINT4 - 4);
576 desc_handle_irq(irq, irq_desc + irq);
577 }
578
579}
580
581static void
582s3c_irq_demux_extint4t7(unsigned int irq,
583 struct irq_desc *desc)
584{
585 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
586 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
587
588 eintpnd &= ~eintmsk;
589 eintpnd &= 0xff; /* only lower irqs */
590
591 /* we may as well handle all the pending IRQs here */
592
593 while (eintpnd) {
594 irq = __ffs(eintpnd);
595 eintpnd &= ~(1<<irq);
596
597 irq += (IRQ_EINT4 - 4);
598
599 desc_handle_irq(irq, irq_desc + irq);
600 }
601}
602
603#ifdef CONFIG_PM
604
605static struct sleep_save irq_save[] = {
606 SAVE_ITEM(S3C2410_INTMSK),
607 SAVE_ITEM(S3C2410_INTSUBMSK),
608}; 41};
609 42
610/* the extint values move between the s3c2410/s3c2440 and the s3c2412 43static int s3c2410_irq_init(void)
611 * so we use an array to hold them, and to calculate the address of
612 * the register at run-time
613*/
614
615static unsigned long save_extint[3];
616static unsigned long save_eintflt[4];
617static unsigned long save_eintmask;
618
619int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
620{ 44{
621 unsigned int i; 45 return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
622
623 for (i = 0; i < ARRAY_SIZE(save_extint); i++)
624 save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
625
626 for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
627 save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
628
629 s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
630 save_eintmask = __raw_readl(S3C24XX_EINTMASK);
631
632 return 0;
633} 46}
634 47
635int s3c24xx_irq_resume(struct sys_device *dev) 48arch_initcall(s3c2410_irq_init);
636{
637 unsigned int i;
638
639 for (i = 0; i < ARRAY_SIZE(save_extint); i++)
640 __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
641
642 for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
643 __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
644
645 s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
646 __raw_writel(save_eintmask, S3C24XX_EINTMASK);
647
648 return 0;
649}
650
651#else
652#define s3c24xx_irq_suspend NULL
653#define s3c24xx_irq_resume NULL
654#endif
655
656/* s3c24xx_init_irq
657 *
658 * Initialise S3C2410 IRQ system
659*/
660
661void __init s3c24xx_init_irq(void)
662{
663 unsigned long pend;
664 unsigned long last;
665 int irqno;
666 int i;
667
668 irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
669
670 /* first, clear all interrupts pending... */
671
672 last = 0;
673 for (i = 0; i < 4; i++) {
674 pend = __raw_readl(S3C24XX_EINTPEND);
675
676 if (pend == 0 || pend == last)
677 break;
678
679 __raw_writel(pend, S3C24XX_EINTPEND);
680 printk("irq: clearing pending ext status %08x\n", (int)pend);
681 last = pend;
682 }
683
684 last = 0;
685 for (i = 0; i < 4; i++) {
686 pend = __raw_readl(S3C2410_INTPND);
687
688 if (pend == 0 || pend == last)
689 break;
690
691 __raw_writel(pend, S3C2410_SRCPND);
692 __raw_writel(pend, S3C2410_INTPND);
693 printk("irq: clearing pending status %08x\n", (int)pend);
694 last = pend;
695 }
696
697 last = 0;
698 for (i = 0; i < 4; i++) {
699 pend = __raw_readl(S3C2410_SUBSRCPND);
700
701 if (pend == 0 || pend == last)
702 break;
703
704 printk("irq: clearing subpending status %08x\n", (int)pend);
705 __raw_writel(pend, S3C2410_SUBSRCPND);
706 last = pend;
707 }
708
709 /* register the main interrupts */
710
711 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
712
713 for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
714 /* set all the s3c2410 internal irqs */
715
716 switch (irqno) {
717 /* deal with the special IRQs (cascaded) */
718
719 case IRQ_EINT4t7:
720 case IRQ_EINT8t23:
721 case IRQ_UART0:
722 case IRQ_UART1:
723 case IRQ_UART2:
724 case IRQ_ADCPARENT:
725 set_irq_chip(irqno, &s3c_irq_level_chip);
726 set_irq_handler(irqno, handle_level_irq);
727 break;
728
729 case IRQ_RESERVED6:
730 case IRQ_RESERVED24:
731 /* no IRQ here */
732 break;
733
734 default:
735 //irqdbf("registering irq %d (s3c irq)\n", irqno);
736 set_irq_chip(irqno, &s3c_irq_chip);
737 set_irq_handler(irqno, handle_edge_irq);
738 set_irq_flags(irqno, IRQF_VALID);
739 }
740 }
741
742 /* setup the cascade irq handlers */
743
744 set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
745 set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
746
747 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
748 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
749 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
750 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
751
752 /* external interrupts */
753
754 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
755 irqdbf("registering irq %d (ext int)\n", irqno);
756 set_irq_chip(irqno, &s3c_irq_eint0t4);
757 set_irq_handler(irqno, handle_edge_irq);
758 set_irq_flags(irqno, IRQF_VALID);
759 }
760
761 for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
762 irqdbf("registering irq %d (extended s3c irq)\n", irqno);
763 set_irq_chip(irqno, &s3c_irqext_chip);
764 set_irq_handler(irqno, handle_edge_irq);
765 set_irq_flags(irqno, IRQF_VALID);
766 }
767
768 /* register the uart interrupts */
769
770 irqdbf("s3c2410: registering external interrupts\n");
771
772 for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
773 irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
774 set_irq_chip(irqno, &s3c_irq_uart0);
775 set_irq_handler(irqno, handle_level_irq);
776 set_irq_flags(irqno, IRQF_VALID);
777 }
778
779 for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
780 irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
781 set_irq_chip(irqno, &s3c_irq_uart1);
782 set_irq_handler(irqno, handle_level_irq);
783 set_irq_flags(irqno, IRQF_VALID);
784 }
785
786 for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
787 irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
788 set_irq_chip(irqno, &s3c_irq_uart2);
789 set_irq_handler(irqno, handle_level_irq);
790 set_irq_flags(irqno, IRQF_VALID);
791 }
792
793 for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
794 irqdbf("registering irq %d (s3c adc irq)\n", irqno);
795 set_irq_chip(irqno, &s3c_irq_adc);
796 set_irq_handler(irqno, handle_edge_irq);
797 set_irq_flags(irqno, IRQF_VALID);
798 }
799
800 irqdbf("s3c2410: registered interrupt handlers\n");
801}
diff --git a/arch/arm/mach-s3c2410/irq.h b/arch/arm/mach-s3c2410/irq.h
deleted file mode 100644
index e5913da3b919..000000000000
--- a/arch/arm/mach-s3c2410/irq.h
+++ /dev/null
@@ -1,107 +0,0 @@
1/* arch/arm/mach-s3c2410/irq.h
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for S3C24XX CPU IRQ support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#define irqdbf(x...)
14#define irqdbf2(x...)
15
16#define EXTINT_OFF (IRQ_EINT4 - 4)
17
18extern struct irq_chip s3c_irq_level_chip;
19
20static inline void
21s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
22 int subcheck)
23{
24 unsigned long mask;
25 unsigned long submask;
26
27 submask = __raw_readl(S3C2410_INTSUBMSK);
28 mask = __raw_readl(S3C2410_INTMSK);
29
30 submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
31
32 /* check to see if we need to mask the parent IRQ */
33
34 if ((submask & subcheck) == subcheck) {
35 __raw_writel(mask | parentbit, S3C2410_INTMSK);
36 }
37
38 /* write back masks */
39 __raw_writel(submask, S3C2410_INTSUBMSK);
40
41}
42
43static inline void
44s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
45{
46 unsigned long mask;
47 unsigned long submask;
48
49 submask = __raw_readl(S3C2410_INTSUBMSK);
50 mask = __raw_readl(S3C2410_INTMSK);
51
52 submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
53 mask &= ~parentbit;
54
55 /* write back masks */
56 __raw_writel(submask, S3C2410_INTSUBMSK);
57 __raw_writel(mask, S3C2410_INTMSK);
58}
59
60
61static inline void
62s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
63{
64 unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
65
66 s3c_irqsub_mask(irqno, parentmask, group);
67
68 __raw_writel(bit, S3C2410_SUBSRCPND);
69
70 /* only ack parent if we've got all the irqs (seems we must
71 * ack, all and hope that the irq system retriggers ok when
72 * the interrupt goes off again)
73 */
74
75 if (1) {
76 __raw_writel(parentmask, S3C2410_SRCPND);
77 __raw_writel(parentmask, S3C2410_INTPND);
78 }
79}
80
81static inline void
82s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
83{
84 unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
85
86 __raw_writel(bit, S3C2410_SUBSRCPND);
87
88 /* only ack parent if we've got all the irqs (seems we must
89 * ack, all and hope that the irq system retriggers ok when
90 * the interrupt goes off again)
91 */
92
93 if (1) {
94 __raw_writel(parentmask, S3C2410_SRCPND);
95 __raw_writel(parentmask, S3C2410_INTPND);
96 }
97}
98
99/* exported for use in arch/arm/mach-s3c2410 */
100
101#ifdef CONFIG_PM
102extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
103#else
104#define s3c_irq_wake NULL
105#endif
106
107extern int s3c_irqext_type(unsigned int irq, unsigned int type);
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c
index 817e2c684410..72f2cc4fcd03 100644
--- a/arch/arm/mach-s3c2410/mach-amlm5900.c
+++ b/arch/arm/mach-s3c2410/mach-amlm5900.c
@@ -1,4 +1,4 @@
1/*********************************************************************** 1/* linux/arch/arm/mach-s3c2410/mach-amlm5900.c
2 * 2 *
3 * linux/arch/arm/mach-s3c2410/mach-amlm5900.c 3 * linux/arch/arm/mach-s3c2410/mach-amlm5900.c
4 * 4 *
@@ -35,7 +35,7 @@
35#include <linux/device.h> 35#include <linux/device.h>
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/proc_fs.h> 37#include <linux/proc_fs.h>
38 38#include <linux/serial_core.h>
39 39
40#include <asm/mach/arch.h> 40#include <asm/mach/arch.h>
41#include <asm/mach/map.h> 41#include <asm/mach/map.h>
@@ -52,8 +52,8 @@
52#include <asm/arch/regs-lcd.h> 52#include <asm/arch/regs-lcd.h>
53#include <asm/arch/regs-gpio.h> 53#include <asm/arch/regs-gpio.h>
54 54
55#include "devs.h" 55#include <asm/plat-s3c24xx/devs.h>
56#include "cpu.h" 56#include <asm/plat-s3c24xx/cpu.h>
57 57
58#ifdef CONFIG_MTD_PARTITIONS 58#ifdef CONFIG_MTD_PARTITIONS
59 59
@@ -113,12 +113,6 @@ static struct platform_device amlm5900_device_nor = {
113#endif 113#endif
114 114
115static struct map_desc amlm5900_iodesc[] __initdata = { 115static struct map_desc amlm5900_iodesc[] __initdata = {
116 {
117 .virtual = (u32)S3C24XX_VA_SPI,
118 .pfn = __phys_to_pfn(S3C2410_PA_SPI),
119 .length = SZ_1M,
120 .type = MT_DEVICE
121 }
122}; 116};
123 117
124#define UCON S3C2410_UCON_DEFAULT 118#define UCON S3C2410_UCON_DEFAULT
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index b8b76757ec54..7b81296427eb 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -50,9 +50,9 @@
50 50
51#include <linux/serial_8250.h> 51#include <linux/serial_8250.h>
52 52
53#include "clock.h" 53#include <asm/plat-s3c24xx/clock.h>
54#include "devs.h" 54#include <asm/plat-s3c24xx/devs.h>
55#include "cpu.h" 55#include <asm/plat-s3c24xx/cpu.h>
56#include "usb-simtec.h" 56#include "usb-simtec.h"
57 57
58#define COPYRIGHT ", (c) 2004-2005 Simtec Electronics" 58#define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 15b625eae499..01c60d0923cd 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -25,23 +25,24 @@
25#include <asm/mach/irq.h> 25#include <asm/mach/irq.h>
26 26
27#include <asm/hardware.h> 27#include <asm/hardware.h>
28#include <asm/hardware/iomd.h>
29#include <asm/io.h> 28#include <asm/io.h>
30#include <asm/irq.h> 29#include <asm/irq.h>
31#include <asm/mach-types.h> 30#include <asm/mach-types.h>
32 31
33
34#include <asm/arch/regs-serial.h> 32#include <asm/arch/regs-serial.h>
35#include <asm/arch/regs-lcd.h> 33#include <asm/arch/regs-lcd.h>
34#include <asm/arch/regs-gpio.h>
35#include <asm/arch/regs-clock.h>
36 36
37#include <asm/arch/h1940.h> 37#include <asm/arch/h1940.h>
38#include <asm/arch/h1940-latch.h> 38#include <asm/arch/h1940-latch.h>
39#include <asm/arch/fb.h> 39#include <asm/arch/fb.h>
40#include <asm/arch/udc.h>
40 41
41#include "clock.h" 42#include <asm/plat-s3c24xx/clock.h>
42#include "devs.h" 43#include <asm/plat-s3c24xx/devs.h>
43#include "cpu.h" 44#include <asm/plat-s3c24xx/cpu.h>
44#include "pm.h" 45#include <asm/plat-s3c24xx/pm.h>
45 46
46static struct map_desc h1940_iodesc[] __initdata = { 47static struct map_desc h1940_iodesc[] __initdata = {
47 [0] = { 48 [0] = {
@@ -102,6 +103,32 @@ void h1940_latch_control(unsigned int clear, unsigned int set)
102 103
103EXPORT_SYMBOL_GPL(h1940_latch_control); 104EXPORT_SYMBOL_GPL(h1940_latch_control);
104 105
106static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
107{
108 printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
109
110 switch (cmd)
111 {
112 case S3C2410_UDC_P_ENABLE :
113 h1940_latch_control(0, H1940_LATCH_USB_DP);
114 break;
115 case S3C2410_UDC_P_DISABLE :
116 h1940_latch_control(H1940_LATCH_USB_DP, 0);
117 break;
118 case S3C2410_UDC_P_RESET :
119 break;
120 default:
121 break;
122 }
123}
124
125static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
126 .udc_command = h1940_udc_pullup,
127 .vbus_pin = S3C2410_GPG5,
128 .vbus_pin_inverted = 1,
129};
130
131
105 132
106/** 133/**
107 * Set lcd on or off 134 * Set lcd on or off
@@ -146,12 +173,19 @@ static struct s3c2410fb_mach_info h1940_lcdcfg __initdata = {
146 .bpp= {16,16,16}, 173 .bpp= {16,16,16},
147}; 174};
148 175
176static struct platform_device s3c_device_leds = {
177 .name = "h1940-leds",
178 .id = -1,
179};
180
149static struct platform_device *h1940_devices[] __initdata = { 181static struct platform_device *h1940_devices[] __initdata = {
150 &s3c_device_usb, 182 &s3c_device_usb,
151 &s3c_device_lcd, 183 &s3c_device_lcd,
152 &s3c_device_wdt, 184 &s3c_device_wdt,
153 &s3c_device_i2c, 185 &s3c_device_i2c,
154 &s3c_device_iis, 186 &s3c_device_iis,
187 &s3c_device_usbgadget,
188 &s3c_device_leds,
155}; 189};
156 190
157static struct s3c24xx_board h1940_board __initdata = { 191static struct s3c24xx_board h1940_board __initdata = {
@@ -179,7 +213,23 @@ static void __init h1940_init_irq(void)
179 213
180static void __init h1940_init(void) 214static void __init h1940_init(void)
181{ 215{
216 u32 tmp;
217
182 s3c24xx_fb_set_platdata(&h1940_lcdcfg); 218 s3c24xx_fb_set_platdata(&h1940_lcdcfg);
219 s3c24xx_udc_set_platdata(&h1940_udc_cfg);
220
221 /* Turn off suspend on both USB ports, and switch the
222 * selectable USB port to USB device mode. */
223
224 s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
225 S3C2410_MISCCR_USBSUSPND0 |
226 S3C2410_MISCCR_USBSUSPND1, 0x0);
227
228 tmp = (
229 0x78 << S3C2410_PLLCON_MDIVSHIFT)
230 | (0x02 << S3C2410_PLLCON_PDIVSHIFT)
231 | (0x03 << S3C2410_PLLCON_SDIVSHIFT);
232 writel(tmp, S3C2410_UPLLCON);
183} 233}
184 234
185MACHINE_START(H1940, "IPAQ-H1940") 235MACHINE_START(H1940, "IPAQ-H1940")
@@ -189,6 +239,6 @@ MACHINE_START(H1940, "IPAQ-H1940")
189 .boot_params = S3C2410_SDRAM_PA + 0x100, 239 .boot_params = S3C2410_SDRAM_PA + 0x100,
190 .map_io = h1940_map_io, 240 .map_io = h1940_map_io,
191 .init_irq = h1940_init_irq, 241 .init_irq = h1940_init_irq,
192 .init_machine = h1940_init, 242 .init_machine = h1940_init,
193 .timer = &s3c24xx_timer, 243 .timer = &s3c24xx_timer,
194MACHINE_END 244MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 0411e9adb54d..261aa4cc0770 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -29,7 +29,6 @@
29#include <asm/mach/irq.h> 29#include <asm/mach/irq.h>
30 30
31#include <asm/hardware.h> 31#include <asm/hardware.h>
32#include <asm/hardware/iomd.h>
33#include <asm/io.h> 32#include <asm/io.h>
34#include <asm/irq.h> 33#include <asm/irq.h>
35#include <asm/mach-types.h> 34#include <asm/mach-types.h>
@@ -38,10 +37,10 @@
38#include <asm/arch/regs-gpio.h> 37#include <asm/arch/regs-gpio.h>
39#include <asm/arch/iic.h> 38#include <asm/arch/iic.h>
40 39
41#include "s3c2410.h" 40#include <asm/plat-s3c24xx/s3c2410.h>
42#include "clock.h" 41#include <asm/plat-s3c24xx/clock.h>
43#include "devs.h" 42#include <asm/plat-s3c24xx/devs.h>
44#include "cpu.h" 43#include <asm/plat-s3c24xx/cpu.h>
45 44
46static struct map_desc n30_iodesc[] __initdata = { 45static struct map_desc n30_iodesc[] __initdata = {
47 /* nothing here yet */ 46 /* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index 2c738b375e4d..c78ab75b44f3 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -32,10 +32,10 @@
32#include <asm/arch/regs-serial.h> 32#include <asm/arch/regs-serial.h>
33#include <asm/arch/regs-gpio.h> 33#include <asm/arch/regs-gpio.h>
34 34
35#include "s3c2410.h" 35#include <asm/plat-s3c24xx/s3c2410.h>
36#include "clock.h" 36#include <asm/plat-s3c24xx/clock.h>
37#include "devs.h" 37#include <asm/plat-s3c24xx/devs.h>
38#include "cpu.h" 38#include <asm/plat-s3c24xx/cpu.h>
39 39
40static struct map_desc otom11_iodesc[] __initdata = { 40static struct map_desc otom11_iodesc[] __initdata = {
41 /* Device area */ 41 /* Device area */
diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
new file mode 100644
index 000000000000..c6a41593de21
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-qt2410.c
@@ -0,0 +1,448 @@
1/* linux/arch/arm/mach-s3c2410/mach-qt2410.c
2 *
3 * Copyright (C) 2006 by OpenMoko, Inc.
4 * Author: Harald Welte <laforge@openmoko.org>
5 * All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/types.h>
26#include <linux/interrupt.h>
27#include <linux/list.h>
28#include <linux/timer.h>
29#include <linux/init.h>
30#include <linux/platform_device.h>
31#include <linux/serial_core.h>
32#include <linux/mmc/protocol.h>
33#include <linux/spi/spi.h>
34#include <linux/spi/spi_bitbang.h>
35
36#include <linux/mtd/mtd.h>
37#include <linux/mtd/nand.h>
38#include <linux/mtd/nand_ecc.h>
39#include <linux/mtd/partitions.h>
40
41#include <asm/mach/arch.h>
42#include <asm/mach/map.h>
43#include <asm/mach/irq.h>
44
45#include <asm/hardware.h>
46#include <asm/io.h>
47#include <asm/irq.h>
48#include <asm/mach-types.h>
49
50#include <asm/arch/regs-gpio.h>
51#include <asm/arch/leds-gpio.h>
52#include <asm/arch/regs-serial.h>
53#include <asm/arch/fb.h>
54#include <asm/arch/nand.h>
55#include <asm/arch/udc.h>
56#include <asm/arch/spi.h>
57#include <asm/arch/spi-gpio.h>
58
59#include <asm/plat-s3c24xx/common-smdk.h>
60#include <asm/plat-s3c24xx/devs.h>
61#include <asm/plat-s3c24xx/cpu.h>
62#include <asm/plat-s3c24xx/pm.h>
63
64static struct map_desc qt2410_iodesc[] __initdata = {
65 { 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
66};
67
68#define UCON S3C2410_UCON_DEFAULT
69#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
70#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
71
72static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
73 [0] = {
74 .hwport = 0,
75 .flags = 0,
76 .ucon = UCON,
77 .ulcon = ULCON,
78 .ufcon = UFCON,
79 },
80 [1] = {
81 .hwport = 1,
82 .flags = 0,
83 .ucon = UCON,
84 .ulcon = ULCON,
85 .ufcon = UFCON,
86 },
87 [2] = {
88 .hwport = 2,
89 .flags = 0,
90 .ucon = UCON,
91 .ulcon = ULCON,
92 .ufcon = UFCON,
93 }
94};
95
96/* LCD driver info */
97
98/* Configuration for 640x480 SHARP LQ080V3DG01 */
99static struct s3c2410fb_mach_info qt2410_biglcd_cfg __initdata = {
100 .regs = {
101
102 .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
103 S3C2410_LCDCON1_TFT |
104 S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
105
106 .lcdcon2 = S3C2410_LCDCON2_VBPD(18) | /* 19 */
107 S3C2410_LCDCON2_LINEVAL(479) |
108 S3C2410_LCDCON2_VFPD(10) | /* 11 */
109 S3C2410_LCDCON2_VSPW(14), /* 15 */
110
111 .lcdcon3 = S3C2410_LCDCON3_HBPD(43) | /* 44 */
112 S3C2410_LCDCON3_HOZVAL(639) | /* 640 */
113 S3C2410_LCDCON3_HFPD(115), /* 116 */
114
115 .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
116 S3C2410_LCDCON4_HSPW(95), /* 96 */
117
118 .lcdcon5 = S3C2410_LCDCON5_FRM565 |
119 S3C2410_LCDCON5_INVVLINE |
120 S3C2410_LCDCON5_INVVFRAME |
121 S3C2410_LCDCON5_PWREN |
122 S3C2410_LCDCON5_HWSWP,
123 },
124
125 .lpcsel = ((0xCE6) & ~7) | 1<<4,
126
127 .width = 640,
128 .height = 480,
129
130 .xres = {
131 .min = 640,
132 .max = 640,
133 .defval = 640,
134 },
135
136 .yres = {
137 .min = 480,
138 .max = 480,
139 .defval = 480,
140 },
141
142 .bpp = {
143 .min = 16,
144 .max = 16,
145 .defval = 16,
146 },
147};
148
149/* Configuration for 480x640 toppoly TD028TTEC1 */
150static struct s3c2410fb_mach_info qt2410_prodlcd_cfg __initdata = {
151 .regs = {
152
153 .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
154 S3C2410_LCDCON1_TFT |
155 S3C2410_LCDCON1_CLKVAL(0x01), /* HCLK/4 */
156
157 .lcdcon2 = S3C2410_LCDCON2_VBPD(1) | /* 2 */
158 S3C2410_LCDCON2_LINEVAL(639) |/* 640 */
159 S3C2410_LCDCON2_VFPD(3) | /* 4 */
160 S3C2410_LCDCON2_VSPW(1), /* 2 */
161
162 .lcdcon3 = S3C2410_LCDCON3_HBPD(7) | /* 8 */
163 S3C2410_LCDCON3_HOZVAL(479) | /* 479 */
164 S3C2410_LCDCON3_HFPD(23), /* 24 */
165
166 .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
167 S3C2410_LCDCON4_HSPW(7), /* 8 */
168
169 .lcdcon5 = S3C2410_LCDCON5_FRM565 |
170 S3C2410_LCDCON5_INVVLINE |
171 S3C2410_LCDCON5_INVVFRAME |
172 S3C2410_LCDCON5_PWREN |
173 S3C2410_LCDCON5_HWSWP,
174 },
175
176 .lpcsel = ((0xCE6) & ~7) | 1<<4,
177
178 .width = 480,
179 .height = 640,
180
181 .xres = {
182 .min = 480,
183 .max = 480,
184 .defval = 480,
185 },
186
187 .yres = {
188 .min = 640,
189 .max = 640,
190 .defval = 640,
191 },
192
193 .bpp = {
194 .min = 16,
195 .max = 16,
196 .defval = 16,
197 },
198};
199
200/* Config for 240x320 LCD */
201static struct s3c2410fb_mach_info qt2410_lcd_cfg __initdata = {
202 .regs = {
203
204 .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |
205 S3C2410_LCDCON1_TFT |
206 S3C2410_LCDCON1_CLKVAL(0x04),
207
208 .lcdcon2 = S3C2410_LCDCON2_VBPD(1) |
209 S3C2410_LCDCON2_LINEVAL(319) |
210 S3C2410_LCDCON2_VFPD(6) |
211 S3C2410_LCDCON2_VSPW(3),
212
213 .lcdcon3 = S3C2410_LCDCON3_HBPD(12) |
214 S3C2410_LCDCON3_HOZVAL(239) |
215 S3C2410_LCDCON3_HFPD(7),
216
217 .lcdcon4 = S3C2410_LCDCON4_MVAL(0) |
218 S3C2410_LCDCON4_HSPW(3),
219
220 .lcdcon5 = S3C2410_LCDCON5_FRM565 |
221 S3C2410_LCDCON5_INVVLINE |
222 S3C2410_LCDCON5_INVVFRAME |
223 S3C2410_LCDCON5_PWREN |
224 S3C2410_LCDCON5_HWSWP,
225 },
226
227 .lpcsel = ((0xCE6) & ~7) | 1<<4,
228
229 .width = 240,
230 .height = 320,
231
232 .xres = {
233 .min = 240,
234 .max = 240,
235 .defval = 240,
236 },
237
238 .yres = {
239 .min = 320,
240 .max = 320,
241 .defval = 320,
242 },
243
244 .bpp = {
245 .min = 16,
246 .max = 16,
247 .defval = 16,
248 },
249};
250
251/* CS8900 */
252
253static struct resource qt2410_cs89x0_resources[] = {
254 [0] = {
255 .start = 0x19000000,
256 .end = 0x19000000 + 16,
257 .flags = IORESOURCE_MEM,
258 },
259 [1] = {
260 .start = IRQ_EINT9,
261 .end = IRQ_EINT9,
262 .flags = IORESOURCE_IRQ,
263 },
264};
265
266static struct platform_device qt2410_cs89x0 = {
267 .name = "cirrus-cs89x0",
268 .num_resources = ARRAY_SIZE(qt2410_cs89x0_resources),
269 .resource = qt2410_cs89x0_resources,
270};
271
272/* LED */
273
274static struct s3c24xx_led_platdata qt2410_pdata_led = {
275 .gpio = S3C2410_GPB0,
276 .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
277 .name = "led",
278 .def_trigger = "timer",
279};
280
281static struct platform_device qt2410_led = {
282 .name = "s3c24xx_led",
283 .id = 0,
284 .dev = {
285 .platform_data = &qt2410_pdata_led,
286 },
287};
288
289/* SPI */
290
291static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
292{
293 switch (cs) {
294 case BITBANG_CS_ACTIVE:
295 s3c2410_gpio_setpin(S3C2410_GPB5, 0);
296 break;
297 case BITBANG_CS_INACTIVE:
298 s3c2410_gpio_setpin(S3C2410_GPB5, 1);
299 break;
300 }
301}
302
303static struct s3c2410_spigpio_info spi_gpio_cfg = {
304 .pin_clk = S3C2410_GPG7,
305 .pin_mosi = S3C2410_GPG6,
306 .pin_miso = S3C2410_GPG5,
307 .chip_select = &spi_gpio_cs,
308};
309
310
311static struct platform_device qt2410_spi = {
312 .name = "s3c24xx-spi-gpio",
313 .id = 1,
314 .dev = {
315 .platform_data = &spi_gpio_cfg,
316 },
317};
318
319/* Board devices */
320
321static struct platform_device *qt2410_devices[] __initdata = {
322 &s3c_device_usb,
323 &s3c_device_lcd,
324 &s3c_device_wdt,
325 &s3c_device_i2c,
326 &s3c_device_iis,
327 &s3c_device_sdi,
328 &s3c_device_usbgadget,
329 &qt2410_spi,
330 &qt2410_cs89x0,
331 &qt2410_led,
332};
333
334static struct s3c24xx_board qt2410_board __initdata = {
335 .devices = qt2410_devices,
336 .devices_count = ARRAY_SIZE(qt2410_devices)
337};
338
339static struct mtd_partition qt2410_nand_part[] = {
340 [0] = {
341 .name = "U-Boot",
342 .size = 0x30000,
343 .offset = 0,
344 },
345 [1] = {
346 .name = "U-Boot environment",
347 .offset = 0x30000,
348 .size = 0x4000,
349 },
350 [2] = {
351 .name = "kernel",
352 .offset = 0x34000,
353 .size = SZ_2M,
354 },
355 [3] = {
356 .name = "initrd",
357 .offset = 0x234000,
358 .size = SZ_4M,
359 },
360 [4] = {
361 .name = "jffs2",
362 .offset = 0x634000,
363 .size = 0x39cc000,
364 },
365};
366
367static struct s3c2410_nand_set qt2410_nand_sets[] = {
368 [0] = {
369 .name = "NAND",
370 .nr_chips = 1,
371 .nr_partitions = ARRAY_SIZE(qt2410_nand_part),
372 .partitions = qt2410_nand_part,
373 },
374};
375
376/* choose a set of timings which should suit most 512Mbit
377 * chips and beyond.
378 */
379
380static struct s3c2410_platform_nand qt2410_nand_info = {
381 .tacls = 20,
382 .twrph0 = 60,
383 .twrph1 = 20,
384 .nr_sets = ARRAY_SIZE(qt2410_nand_sets),
385 .sets = qt2410_nand_sets,
386};
387
388/* UDC */
389
390static struct s3c2410_udc_mach_info qt2410_udc_cfg = {
391};
392
393static char tft_type = 's';
394
395static int __init qt2410_tft_setup(char *str)
396{
397 tft_type = str[0];
398 return 1;
399}
400
401__setup("tft=", qt2410_tft_setup);
402
403static void __init qt2410_map_io(void)
404{
405 s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
406 s3c24xx_init_clocks(12*1000*1000);
407 s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
408 s3c24xx_set_board(&qt2410_board);
409}
410
411static void __init qt2410_machine_init(void)
412{
413 s3c_device_nand.dev.platform_data = &qt2410_nand_info;
414
415 switch (tft_type) {
416 case 'p': /* production */
417 s3c24xx_fb_set_platdata(&qt2410_prodlcd_cfg);
418 break;
419 case 'b': /* big */
420 s3c24xx_fb_set_platdata(&qt2410_biglcd_cfg);
421 break;
422 case 's': /* small */
423 default:
424 s3c24xx_fb_set_platdata(&qt2410_lcd_cfg);
425 break;
426 }
427
428 s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT);
429 s3c2410_gpio_setpin(S3C2410_GPB0, 1);
430
431 s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
432
433 s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
434
435 s3c2410_pm_init();
436}
437
438MACHINE_START(QT2410, "QT2410")
439 .phys_io = S3C2410_PA_UART,
440 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
441 .boot_params = S3C2410_SDRAM_PA + 0x100,
442 .map_io = qt2410_map_io,
443 .init_irq = s3c24xx_init_irq,
444 .init_machine = qt2410_machine_init,
445 .timer = &s3c24xx_timer,
446MACHINE_END
447
448
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 01c0c986d827..57b8a80f33d0 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -1,4 +1,4 @@
1/*********************************************************************** 1/* linux/arch/arm/mach-s3c2410/mach-smdk2410.c
2 * 2 *
3 * linux/arch/arm/mach-s3c2410/mach-smdk2410.c 3 * linux/arch/arm/mach-s3c2410/mach-smdk2410.c
4 * 4 *
@@ -49,10 +49,10 @@
49 49
50#include <asm/arch/regs-serial.h> 50#include <asm/arch/regs-serial.h>
51 51
52#include "devs.h" 52#include <asm/plat-s3c24xx/devs.h>
53#include "cpu.h" 53#include <asm/plat-s3c24xx/cpu.h>
54 54
55#include "common-smdk.h" 55#include <asm/plat-s3c24xx/common-smdk.h>
56 56
57static struct map_desc smdk2410_iodesc[] __initdata = { 57static struct map_desc smdk2410_iodesc[] __initdata = {
58 /* nothing here yet */ 58 /* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index a382fc095110..c947c75bcbf0 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -43,9 +43,9 @@
43#include <asm/arch/regs-gpio.h> 43#include <asm/arch/regs-gpio.h>
44#include <asm/arch/leds-gpio.h> 44#include <asm/arch/leds-gpio.h>
45 45
46#include "clock.h" 46#include <asm/plat-s3c24xx/clock.h>
47#include "devs.h" 47#include <asm/plat-s3c24xx/devs.h>
48#include "cpu.h" 48#include <asm/plat-s3c24xx/cpu.h>
49#include "usb-simtec.h" 49#include "usb-simtec.h"
50 50
51/* macros for virtual address mods for the io space entries */ 51/* macros for virtual address mods for the io space entries */
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index ebf294dd31da..3b3a7db4e0dd 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -1,11 +1,9 @@
1/* linux/arch/arm/mach-s3c2410/pm.c 1/* linux/arch/arm/mach-s3c2410/pm.c
2 * 2 *
3 * Copyright (c) 2004,2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * S3C24XX Power Manager (Suspend-To-RAM) support 6 * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
7 *
8 * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
9 * 7 *
10 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -20,640 +18,139 @@
20 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Parts based on arch/arm/mach-pxa/pm.c
25 *
26 * Thanks to Dimitry Andric for debugging
27*/ 21*/
28 22
29#include <linux/init.h> 23#include <linux/init.h>
30#include <linux/suspend.h> 24#include <linux/suspend.h>
31#include <linux/errno.h> 25#include <linux/errno.h>
32#include <linux/time.h> 26#include <linux/time.h>
33#include <linux/interrupt.h> 27#include <linux/sysdev.h>
34#include <linux/crc32.h>
35#include <linux/ioport.h>
36#include <linux/delay.h>
37#include <linux/serial_core.h>
38 28
39#include <asm/cacheflush.h>
40#include <asm/hardware.h> 29#include <asm/hardware.h>
41#include <asm/io.h> 30#include <asm/io.h>
42 31
43#include <asm/arch/regs-serial.h> 32#include <asm/mach-types.h>
44#include <asm/arch/regs-clock.h>
45#include <asm/arch/regs-gpio.h>
46#include <asm/arch/regs-mem.h>
47#include <asm/arch/regs-irq.h>
48
49#include <asm/mach/time.h>
50
51#include "pm.h"
52
53/* for external use */
54
55unsigned long s3c_pm_flags;
56
57#define PFX "s3c24xx-pm: "
58
59static struct sleep_save core_save[] = {
60 SAVE_ITEM(S3C2410_LOCKTIME),
61 SAVE_ITEM(S3C2410_CLKCON),
62
63 /* we restore the timings here, with the proviso that the board
64 * brings the system up in an slower, or equal frequency setting
65 * to the original system.
66 *
67 * if we cannot guarantee this, then things are going to go very
68 * wrong here, as we modify the refresh and both pll settings.
69 */
70
71 SAVE_ITEM(S3C2410_BWSCON),
72 SAVE_ITEM(S3C2410_BANKCON0),
73 SAVE_ITEM(S3C2410_BANKCON1),
74 SAVE_ITEM(S3C2410_BANKCON2),
75 SAVE_ITEM(S3C2410_BANKCON3),
76 SAVE_ITEM(S3C2410_BANKCON4),
77 SAVE_ITEM(S3C2410_BANKCON5),
78
79 SAVE_ITEM(S3C2410_CLKDIVN),
80 SAVE_ITEM(S3C2410_MPLLCON),
81 SAVE_ITEM(S3C2410_UPLLCON),
82 SAVE_ITEM(S3C2410_CLKSLOW),
83 SAVE_ITEM(S3C2410_REFRESH),
84};
85
86static struct sleep_save gpio_save[] = {
87 SAVE_ITEM(S3C2410_GPACON),
88 SAVE_ITEM(S3C2410_GPADAT),
89
90 SAVE_ITEM(S3C2410_GPBCON),
91 SAVE_ITEM(S3C2410_GPBDAT),
92 SAVE_ITEM(S3C2410_GPBUP),
93
94 SAVE_ITEM(S3C2410_GPCCON),
95 SAVE_ITEM(S3C2410_GPCDAT),
96 SAVE_ITEM(S3C2410_GPCUP),
97
98 SAVE_ITEM(S3C2410_GPDCON),
99 SAVE_ITEM(S3C2410_GPDDAT),
100 SAVE_ITEM(S3C2410_GPDUP),
101
102 SAVE_ITEM(S3C2410_GPECON),
103 SAVE_ITEM(S3C2410_GPEDAT),
104 SAVE_ITEM(S3C2410_GPEUP),
105
106 SAVE_ITEM(S3C2410_GPFCON),
107 SAVE_ITEM(S3C2410_GPFDAT),
108 SAVE_ITEM(S3C2410_GPFUP),
109 33
110 SAVE_ITEM(S3C2410_GPGCON), 34#include <asm/arch/regs-gpio.h>
111 SAVE_ITEM(S3C2410_GPGDAT), 35#include <asm/arch/h1940.h>
112 SAVE_ITEM(S3C2410_GPGUP),
113
114 SAVE_ITEM(S3C2410_GPHCON),
115 SAVE_ITEM(S3C2410_GPHDAT),
116 SAVE_ITEM(S3C2410_GPHUP),
117 36
118 SAVE_ITEM(S3C2410_DCLKCON), 37#include <asm/plat-s3c24xx/cpu.h>
119}; 38#include <asm/plat-s3c24xx/pm.h>
120 39
121#ifdef CONFIG_S3C2410_PM_DEBUG 40#ifdef CONFIG_S3C2410_PM_DEBUG
122 41extern void pm_dbg(const char *fmt, ...);
123#define SAVE_UART(va) \
124 SAVE_ITEM((va) + S3C2410_ULCON), \
125 SAVE_ITEM((va) + S3C2410_UCON), \
126 SAVE_ITEM((va) + S3C2410_UFCON), \
127 SAVE_ITEM((va) + S3C2410_UMCON), \
128 SAVE_ITEM((va) + S3C2410_UBRDIV)
129
130static struct sleep_save uart_save[] = {
131 SAVE_UART(S3C24XX_VA_UART0),
132 SAVE_UART(S3C24XX_VA_UART1),
133#ifndef CONFIG_CPU_S3C2400
134 SAVE_UART(S3C24XX_VA_UART2),
135#endif
136};
137
138/* debug
139 *
140 * we send the debug to printascii() to allow it to be seen if the
141 * system never wakes up from the sleep
142*/
143
144extern void printascii(const char *);
145
146void pm_dbg(const char *fmt, ...)
147{
148 va_list va;
149 char buff[256];
150
151 va_start(va, fmt);
152 vsprintf(buff, fmt, va);
153 va_end(va);
154
155 printascii(buff);
156}
157
158static void s3c2410_pm_debug_init(void)
159{
160 unsigned long tmp = __raw_readl(S3C2410_CLKCON);
161
162 /* re-start uart clocks */
163 tmp |= S3C2410_CLKCON_UART0;
164 tmp |= S3C2410_CLKCON_UART1;
165 tmp |= S3C2410_CLKCON_UART2;
166
167 __raw_writel(tmp, S3C2410_CLKCON);
168 udelay(10);
169}
170
171#define DBG(fmt...) pm_dbg(fmt) 42#define DBG(fmt...) pm_dbg(fmt)
172#else 43#else
173#define DBG(fmt...) printk(KERN_DEBUG fmt) 44#define DBG(fmt...) printk(KERN_DEBUG fmt)
174
175#define s3c2410_pm_debug_init() do { } while(0)
176
177static struct sleep_save uart_save[] = {};
178#endif 45#endif
179 46
180#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0 47static void s3c2410_pm_prepare(void)
181
182/* suspend checking code...
183 *
184 * this next area does a set of crc checks over all the installed
185 * memory, so the system can verify if the resume was ok.
186 *
187 * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
188 * increasing it will mean that the area corrupted will be less easy to spot,
189 * and reducing the size will cause the CRC save area to grow
190*/
191
192#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
193
194static u32 crc_size; /* size needed for the crc block */
195static u32 *crcs; /* allocated over suspend/resume */
196
197typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
198
199/* s3c2410_pm_run_res
200 *
201 * go thorugh the given resource list, and look for system ram
202*/
203
204static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
205{
206 while (ptr != NULL) {
207 if (ptr->child != NULL)
208 s3c2410_pm_run_res(ptr->child, fn, arg);
209
210 if ((ptr->flags & IORESOURCE_MEM) &&
211 strcmp(ptr->name, "System RAM") == 0) {
212 DBG("Found system RAM at %08lx..%08lx\n",
213 ptr->start, ptr->end);
214 arg = (fn)(ptr, arg);
215 }
216
217 ptr = ptr->sibling;
218 }
219}
220
221static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
222{
223 s3c2410_pm_run_res(&iomem_resource, fn, arg);
224}
225
226static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
227{
228 u32 size = (u32)(res->end - res->start)+1;
229
230 size += CHECK_CHUNKSIZE-1;
231 size /= CHECK_CHUNKSIZE;
232
233 DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
234
235 *val += size * sizeof(u32);
236 return val;
237}
238
239/* s3c2410_pm_prepare_check
240 *
241 * prepare the necessary information for creating the CRCs. This
242 * must be done before the final save, as it will require memory
243 * allocating, and thus touching bits of the kernel we do not
244 * know about.
245*/
246
247static void s3c2410_pm_check_prepare(void)
248{ 48{
249 crc_size = 0; 49 /* ensure at least GSTATUS3 has the resume address */
250 50
251 s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size); 51 __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
252 52
253 DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size); 53 DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
54 DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
254 55
255 crcs = kmalloc(crc_size+4, GFP_KERNEL); 56 if (machine_is_h1940()) {
256 if (crcs == NULL) 57 void *base = phys_to_virt(H1940_SUSPEND_CHECK);
257 printk(KERN_ERR "Cannot allocated CRC save area\n"); 58 unsigned long ptr;
258} 59 unsigned long calc = 0;
259 60
260static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val) 61 /* generate check for the bootloader to check on resume */
261{
262 unsigned long addr, left;
263 62
264 for (addr = res->start; addr < res->end; 63 for (ptr = 0; ptr < 0x40000; ptr += 0x400)
265 addr += CHECK_CHUNKSIZE) { 64 calc += __raw_readl(base+ptr);
266 left = res->end - addr;
267 65
268 if (left > CHECK_CHUNKSIZE) 66 __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
269 left = CHECK_CHUNKSIZE;
270
271 *val = crc32_le(~0, phys_to_virt(addr), left);
272 val++;
273 } 67 }
274 68
275 return val; 69 /* the RX3715 uses similar code and the same H1940 and the
276} 70 * same offsets for resume and checksum pointers */
277
278/* s3c2410_pm_check_store
279 *
280 * compute the CRC values for the memory blocks before the final
281 * sleep.
282*/
283
284static void s3c2410_pm_check_store(void)
285{
286 if (crcs != NULL)
287 s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
288}
289
290/* in_region
291 *
292 * return TRUE if the area defined by ptr..ptr+size contatins the
293 * what..what+whatsz
294*/
295
296static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
297{
298 if ((what+whatsz) < ptr)
299 return 0;
300
301 if (what > (ptr+size))
302 return 0;
303
304 return 1;
305}
306
307static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
308{
309 void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
310 unsigned long addr;
311 unsigned long left;
312 void *ptr;
313 u32 calc;
314
315 for (addr = res->start; addr < res->end;
316 addr += CHECK_CHUNKSIZE) {
317 left = res->end - addr;
318 71
319 if (left > CHECK_CHUNKSIZE) 72 if (machine_is_rx3715()) {
320 left = CHECK_CHUNKSIZE; 73 void *base = phys_to_virt(H1940_SUSPEND_CHECK);
74 unsigned long ptr;
75 unsigned long calc = 0;
321 76
322 ptr = phys_to_virt(addr); 77 /* generate check for the bootloader to check on resume */
323 78
324 if (in_region(ptr, left, crcs, crc_size)) { 79 for (ptr = 0; ptr < 0x40000; ptr += 0x4)
325 DBG("skipping %08lx, has crc block in\n", addr); 80 calc += __raw_readl(base+ptr);
326 goto skip_check;
327 }
328 81
329 if (in_region(ptr, left, save_at, 32*4 )) { 82 __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
330 DBG("skipping %08lx, has save block in\n", addr);
331 goto skip_check;
332 }
333
334 /* calculate and check the checksum */
335
336 calc = crc32_le(~0, ptr, left);
337 if (calc != *val) {
338 printk(KERN_ERR PFX "Restore CRC error at "
339 "%08lx (%08x vs %08x)\n", addr, calc, *val);
340
341 DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
342 addr, calc, *val);
343 }
344
345 skip_check:
346 val++;
347 } 83 }
348 84
349 return val; 85 if ( machine_is_aml_m5900() )
350} 86 s3c2410_gpio_setpin(S3C2410_GPF2, 1);
351 87
352/* s3c2410_pm_check_restore
353 *
354 * check the CRCs after the restore event and free the memory used
355 * to hold them
356*/
357
358static void s3c2410_pm_check_restore(void)
359{
360 if (crcs != NULL) {
361 s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
362 kfree(crcs);
363 crcs = NULL;
364 }
365} 88}
366 89
367#else 90static int s3c2410_pm_resume(struct sys_device *dev)
368
369#define s3c2410_pm_check_prepare() do { } while(0)
370#define s3c2410_pm_check_restore() do { } while(0)
371#define s3c2410_pm_check_store() do { } while(0)
372#endif
373
374/* helper functions to save and restore register state */
375
376void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
377{ 91{
378 for (; count > 0; count--, ptr++) { 92 unsigned long tmp;
379 ptr->val = __raw_readl(ptr->reg);
380 DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
381 }
382}
383 93
384/* s3c2410_pm_do_restore 94 /* unset the return-from-sleep flag, to ensure reset */
385 *
386 * restore the system from the given list of saved registers
387 *
388 * Note, we do not use DBG() in here, as the system may not have
389 * restore the UARTs state yet
390*/
391 95
392void s3c2410_pm_do_restore(struct sleep_save *ptr, int count) 96 tmp = __raw_readl(S3C2410_GSTATUS2);
393{ 97 tmp &= S3C2410_GSTATUS2_OFFRESET;
394 for (; count > 0; count--, ptr++) { 98 __raw_writel(tmp, S3C2410_GSTATUS2);
395 printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
396 ptr->reg, ptr->val, __raw_readl(ptr->reg));
397
398 __raw_writel(ptr->val, ptr->reg);
399 }
400}
401 99
402/* s3c2410_pm_do_restore_core 100 if ( machine_is_aml_m5900() )
403 * 101 s3c2410_gpio_setpin(S3C2410_GPF2, 0);
404 * similar to s3c2410_pm_do_restore_core
405 *
406 * WARNING: Do not put any debug in here that may effect memory or use
407 * peripherals, as things may be changing!
408*/
409 102
410static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count) 103 return 0;
411{
412 for (; count > 0; count--, ptr++) {
413 __raw_writel(ptr->val, ptr->reg);
414 }
415} 104}
416 105
417/* s3c2410_pm_show_resume_irqs 106static int s3c2410_pm_add(struct sys_device *dev)
418 *
419 * print any IRQs asserted at resume time (ie, we woke from)
420*/
421
422static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
423 unsigned long mask)
424{ 107{
425 int i; 108 pm_cpu_prep = s3c2410_pm_prepare;
109 pm_cpu_sleep = s3c2410_cpu_suspend;
426 110
427 which &= ~mask; 111 return 0;
428
429 for (i = 0; i <= 31; i++) {
430 if ((which) & (1L<<i)) {
431 DBG("IRQ %d asserted at resume\n", start+i);
432 }
433 }
434} 112}
435 113
436/* s3c2410_pm_check_resume_pin 114#if defined(CONFIG_CPU_S3C2410)
437 * 115static struct sysdev_driver s3c2410_pm_driver = {
438 * check to see if the pin is configured correctly for sleep mode, and 116 .add = s3c2410_pm_add,
439 * make any necessary adjustments if it is not 117 .resume = s3c2410_pm_resume,
440*/ 118};
441
442static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
443{
444 unsigned long irqstate;
445 unsigned long pinstate;
446 int irq = s3c2410_gpio_getirq(pin);
447
448 if (irqoffs < 4)
449 irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
450 else
451 irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
452
453 pinstate = s3c2410_gpio_getcfg(pin);
454
455 if (!irqstate) {
456 if (pinstate == S3C2410_GPIO_IRQ)
457 DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
458 } else {
459 if (pinstate == S3C2410_GPIO_IRQ) {
460 DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
461 s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
462 }
463 }
464}
465 119
466/* s3c2410_pm_configure_extint 120/* register ourselves */
467 *
468 * configure all external interrupt pins
469*/
470 121
471static void s3c2410_pm_configure_extint(void) 122static int __init s3c2410_pm_drvinit(void)
472{ 123{
473 int pin; 124 return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
474
475 /* for each of the external interrupts (EINT0..EINT15) we
476 * need to check wether it is an external interrupt source,
477 * and then configure it as an input if it is not
478 */
479
480 for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
481 s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
482 }
483
484 for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
485 s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
486 }
487} 125}
488 126
489void (*pm_cpu_prep)(void); 127arch_initcall(s3c2410_pm_drvinit);
490void (*pm_cpu_sleep)(void); 128#endif
491
492#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
493
494/* s3c2410_pm_enter
495 *
496 * central control for sleep/resume process
497*/
498
499static int s3c2410_pm_enter(suspend_state_t state)
500{
501 unsigned long regs_save[16];
502
503 /* ensure the debug is initialised (if enabled) */
504
505 s3c2410_pm_debug_init();
506
507 DBG("s3c2410_pm_enter(%d)\n", state);
508
509 if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
510 printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
511 return -EINVAL;
512 }
513
514 if (state != PM_SUSPEND_MEM) {
515 printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
516 return -EINVAL;
517 }
518
519 /* check if we have anything to wake-up with... bad things seem
520 * to happen if you suspend with no wakeup (system will often
521 * require a full power-cycle)
522 */
523
524 if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
525 !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
526 printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
527 printk(KERN_ERR PFX "Aborting sleep\n");
528 return -EINVAL;
529 }
530
531 /* prepare check area if configured */
532
533 s3c2410_pm_check_prepare();
534
535 /* store the physical address of the register recovery block */
536
537 s3c2410_sleep_save_phys = virt_to_phys(regs_save);
538
539 DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
540
541 /* save all necessary core registers not covered by the drivers */
542
543 s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
544 s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
545 s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
546
547 /* set the irq configuration for wake */
548
549 s3c2410_pm_configure_extint();
550
551 DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
552 s3c_irqwake_intmask, s3c_irqwake_eintmask);
553
554 __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
555 __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
556
557 /* ack any outstanding external interrupts before we go to sleep */
558
559 __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
560 __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
561 __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
562
563 /* call cpu specific preperation */
564
565 pm_cpu_prep();
566
567 /* flush cache back to ram */
568
569 flush_cache_all();
570
571 s3c2410_pm_check_store();
572
573 /* send the cpu to sleep... */
574
575 __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
576
577 /* s3c2410_cpu_save will also act as our return point from when
578 * we resume as it saves its own register state, so use the return
579 * code to differentiate return from save and return from sleep */
580
581 if (s3c2410_cpu_save(regs_save) == 0) {
582 flush_cache_all();
583 pm_cpu_sleep();
584 }
585
586 /* restore the cpu state */
587
588 cpu_init();
589
590 /* restore the system state */
591
592 s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
593 s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
594 s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
595
596 s3c2410_pm_debug_init();
597
598 /* check what irq (if any) restored the system */
599
600 DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
601 __raw_readl(S3C2410_SRCPND),
602 __raw_readl(S3C2410_EINTPEND));
603
604 s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
605 s3c_irqwake_intmask);
606
607 s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
608 s3c_irqwake_eintmask);
609
610 DBG("post sleep, preparing to return\n");
611
612 s3c2410_pm_check_restore();
613
614 /* ok, let's return from sleep */
615 129
616 DBG("S3C2410 PM Resume (post-restore)\n"); 130#if defined(CONFIG_CPU_S3C2440)
617 return 0; 131static struct sysdev_driver s3c2440_pm_driver = {
618} 132 .add = s3c2410_pm_add,
133 .resume = s3c2410_pm_resume,
134};
619 135
620/* 136static int __init s3c2440_pm_drvinit(void)
621 * Called after processes are frozen, but before we shut down devices.
622 */
623static int s3c2410_pm_prepare(suspend_state_t state)
624{ 137{
625 return 0; 138 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
626} 139}
627 140
628/* 141arch_initcall(s3c2440_pm_drvinit);
629 * Called after devices are re-setup, but before processes are thawed. 142#endif
630 */
631static int s3c2410_pm_finish(suspend_state_t state)
632{
633 return 0;
634}
635 143
636/* 144#if defined(CONFIG_CPU_S3C2442)
637 * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. 145static struct sysdev_driver s3c2442_pm_driver = {
638 */ 146 .add = s3c2410_pm_add,
639static struct pm_ops s3c2410_pm_ops = { 147 .resume = s3c2410_pm_resume,
640 .pm_disk_mode = PM_DISK_FIRMWARE,
641 .prepare = s3c2410_pm_prepare,
642 .enter = s3c2410_pm_enter,
643 .finish = s3c2410_pm_finish,
644}; 148};
645 149
646/* s3c2410_pm_init 150static int __init s3c2442_pm_drvinit(void)
647 *
648 * Attach the power management functions. This should be called
649 * from the board specific initialisation if the board supports
650 * it.
651*/
652
653int __init s3c2410_pm_init(void)
654{ 151{
655 printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n"); 152 return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
656
657 pm_set_ops(&s3c2410_pm_ops);
658 return 0;
659} 153}
154
155arch_initcall(s3c2442_pm_drvinit);
156#endif
diff --git a/arch/arm/mach-s3c2410/pm.h b/arch/arm/mach-s3c2410/pm.h
deleted file mode 100644
index ffe197a119fb..000000000000
--- a/arch/arm/mach-s3c2410/pm.h
+++ /dev/null
@@ -1,73 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/pm.h
2 *
3 * Copyright (c) 2004 Simtec Electronics
4 * Written by Ben Dooks, <ben@simtec.co.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9*/
10
11/* s3c2410_pm_init
12 *
13 * called from board at initialisation time to setup the power
14 * management
15*/
16
17#ifdef CONFIG_PM
18
19extern __init int s3c2410_pm_init(void);
20
21#else
22
23static inline int s3c2410_pm_init(void)
24{
25 return 0;
26}
27#endif
28
29/* configuration for the IRQ mask over sleep */
30extern unsigned long s3c_irqwake_intmask;
31extern unsigned long s3c_irqwake_eintmask;
32
33/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
34extern unsigned long s3c_irqwake_intallow;
35extern unsigned long s3c_irqwake_eintallow;
36
37/* per-cpu sleep functions */
38
39extern void (*pm_cpu_prep)(void);
40extern void (*pm_cpu_sleep)(void);
41
42/* Flags for PM Control */
43
44extern unsigned long s3c_pm_flags;
45
46/* from sleep.S */
47
48extern int s3c2410_cpu_save(unsigned long *saveblk);
49extern void s3c2410_cpu_suspend(void);
50extern void s3c2410_cpu_resume(void);
51
52extern unsigned long s3c2410_sleep_save_phys;
53
54/* sleep save info */
55
56struct sleep_save {
57 void __iomem *reg;
58 unsigned long val;
59};
60
61#define SAVE_ITEM(x) \
62 { .reg = (x) }
63
64extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
65extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
66
67#ifdef CONFIG_PM
68extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
69extern int s3c24xx_irq_resume(struct sys_device *dev);
70#else
71#define s3c24xx_irq_suspend NULL
72#define s3c24xx_irq_resume NULL
73#endif
diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/arch/arm/mach-s3c2410/s3c2400.h
deleted file mode 100644
index 8b2394e1ed40..000000000000
--- a/arch/arm/mach-s3c2410/s3c2400.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* arch/arm/mach-s3c2410/s3c2400.h
2 *
3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for S3C2400 cpu support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Modifications:
13 * 09-Fev-2006 LCVR First version, based on s3c2410.h
14*/
15
16#ifdef CONFIG_CPU_S3C2400
17
18extern int s3c2400_init(void);
19
20extern void s3c2400_map_io(struct map_desc *mach_desc, int size);
21
22extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no);
23
24extern void s3c2400_init_clocks(int xtal);
25
26#else
27#define s3c2400_init_clocks NULL
28#define s3c2400_init_uarts NULL
29#define s3c2400_map_io NULL
30#define s3c2400_init NULL
31#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
deleted file mode 100644
index 992cc6af230e..000000000000
--- a/arch/arm/mach-s3c2410/s3c2410-clock.c
+++ /dev/null
@@ -1,276 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/s3c2410-clock.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410,S3C2440,S3C2442 Clock control support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/list.h>
27#include <linux/errno.h>
28#include <linux/err.h>
29#include <linux/sysdev.h>
30#include <linux/clk.h>
31#include <linux/mutex.h>
32#include <linux/delay.h>
33#include <linux/serial_core.h>
34
35#include <asm/mach/map.h>
36
37#include <asm/hardware.h>
38#include <asm/io.h>
39
40#include <asm/arch/regs-serial.h>
41#include <asm/arch/regs-clock.h>
42#include <asm/arch/regs-gpio.h>
43
44#include "s3c2410.h"
45#include "clock.h"
46#include "cpu.h"
47
48int s3c2410_clkcon_enable(struct clk *clk, int enable)
49{
50 unsigned int clocks = clk->ctrlbit;
51 unsigned long clkcon;
52
53 clkcon = __raw_readl(S3C2410_CLKCON);
54
55 if (enable)
56 clkcon |= clocks;
57 else
58 clkcon &= ~clocks;
59
60 /* ensure none of the special function bits set */
61 clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
62
63 __raw_writel(clkcon, S3C2410_CLKCON);
64
65 return 0;
66}
67
68static int s3c2410_upll_enable(struct clk *clk, int enable)
69{
70 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
71 unsigned long orig = clkslow;
72
73 if (enable)
74 clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
75 else
76 clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
77
78 __raw_writel(clkslow, S3C2410_CLKSLOW);
79
80 /* if we started the UPLL, then allow to settle */
81
82 if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
83 udelay(200);
84
85 return 0;
86}
87
88/* standard clock definitions */
89
90static struct clk init_clocks_disable[] = {
91 {
92 .name = "nand",
93 .id = -1,
94 .parent = &clk_h,
95 .enable = s3c2410_clkcon_enable,
96 .ctrlbit = S3C2410_CLKCON_NAND,
97 }, {
98 .name = "sdi",
99 .id = -1,
100 .parent = &clk_p,
101 .enable = s3c2410_clkcon_enable,
102 .ctrlbit = S3C2410_CLKCON_SDI,
103 }, {
104 .name = "adc",
105 .id = -1,
106 .parent = &clk_p,
107 .enable = s3c2410_clkcon_enable,
108 .ctrlbit = S3C2410_CLKCON_ADC,
109 }, {
110 .name = "i2c",
111 .id = -1,
112 .parent = &clk_p,
113 .enable = s3c2410_clkcon_enable,
114 .ctrlbit = S3C2410_CLKCON_IIC,
115 }, {
116 .name = "iis",
117 .id = -1,
118 .parent = &clk_p,
119 .enable = s3c2410_clkcon_enable,
120 .ctrlbit = S3C2410_CLKCON_IIS,
121 }, {
122 .name = "spi",
123 .id = -1,
124 .parent = &clk_p,
125 .enable = s3c2410_clkcon_enable,
126 .ctrlbit = S3C2410_CLKCON_SPI,
127 }
128};
129
130static struct clk init_clocks[] = {
131 {
132 .name = "lcd",
133 .id = -1,
134 .parent = &clk_h,
135 .enable = s3c2410_clkcon_enable,
136 .ctrlbit = S3C2410_CLKCON_LCDC,
137 }, {
138 .name = "gpio",
139 .id = -1,
140 .parent = &clk_p,
141 .enable = s3c2410_clkcon_enable,
142 .ctrlbit = S3C2410_CLKCON_GPIO,
143 }, {
144 .name = "usb-host",
145 .id = -1,
146 .parent = &clk_h,
147 .enable = s3c2410_clkcon_enable,
148 .ctrlbit = S3C2410_CLKCON_USBH,
149 }, {
150 .name = "usb-device",
151 .id = -1,
152 .parent = &clk_h,
153 .enable = s3c2410_clkcon_enable,
154 .ctrlbit = S3C2410_CLKCON_USBD,
155 }, {
156 .name = "timers",
157 .id = -1,
158 .parent = &clk_p,
159 .enable = s3c2410_clkcon_enable,
160 .ctrlbit = S3C2410_CLKCON_PWMT,
161 }, {
162 .name = "uart",
163 .id = 0,
164 .parent = &clk_p,
165 .enable = s3c2410_clkcon_enable,
166 .ctrlbit = S3C2410_CLKCON_UART0,
167 }, {
168 .name = "uart",
169 .id = 1,
170 .parent = &clk_p,
171 .enable = s3c2410_clkcon_enable,
172 .ctrlbit = S3C2410_CLKCON_UART1,
173 }, {
174 .name = "uart",
175 .id = 2,
176 .parent = &clk_p,
177 .enable = s3c2410_clkcon_enable,
178 .ctrlbit = S3C2410_CLKCON_UART2,
179 }, {
180 .name = "rtc",
181 .id = -1,
182 .parent = &clk_p,
183 .enable = s3c2410_clkcon_enable,
184 .ctrlbit = S3C2410_CLKCON_RTC,
185 }, {
186 .name = "watchdog",
187 .id = -1,
188 .parent = &clk_p,
189 .ctrlbit = 0,
190 }, {
191 .name = "usb-bus-host",
192 .id = -1,
193 .parent = &clk_usb_bus,
194 }, {
195 .name = "usb-bus-gadget",
196 .id = -1,
197 .parent = &clk_usb_bus,
198 },
199};
200
201/* s3c2410_baseclk_add()
202 *
203 * Add all the clocks used by the s3c2410 or compatible CPUs
204 * such as the S3C2440 and S3C2442.
205 *
206 * We cannot use a system device as we are needed before any
207 * of the init-calls that initialise the devices are actually
208 * done.
209*/
210
211int __init s3c2410_baseclk_add(void)
212{
213 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
214 unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
215 struct clk *clkp;
216 struct clk *xtal;
217 int ret;
218 int ptr;
219
220 clk_upll.enable = s3c2410_upll_enable;
221
222 if (s3c24xx_register_clock(&clk_usb_bus) < 0)
223 printk(KERN_ERR "failed to register usb bus clock\n");
224
225 /* register clocks from clock array */
226
227 clkp = init_clocks;
228 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
229 /* ensure that we note the clock state */
230
231 clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
232
233 ret = s3c24xx_register_clock(clkp);
234 if (ret < 0) {
235 printk(KERN_ERR "Failed to register clock %s (%d)\n",
236 clkp->name, ret);
237 }
238 }
239
240 /* We must be careful disabling the clocks we are not intending to
241 * be using at boot time, as subsytems such as the LCD which do
242 * their own DMA requests to the bus can cause the system to lockup
243 * if they where in the middle of requesting bus access.
244 *
245 * Disabling the LCD clock if the LCD is active is very dangerous,
246 * and therefore the bootloader should be careful to not enable
247 * the LCD clock if it is not needed.
248 */
249
250 /* install (and disable) the clocks we do not need immediately */
251
252 clkp = init_clocks_disable;
253 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
254
255 ret = s3c24xx_register_clock(clkp);
256 if (ret < 0) {
257 printk(KERN_ERR "Failed to register clock %s (%d)\n",
258 clkp->name, ret);
259 }
260
261 s3c2410_clkcon_enable(clkp, 0);
262 }
263
264 /* show the clock-slow value */
265
266 xtal = clk_get(NULL, "xtal");
267
268 printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
269 print_mhz(clk_get_rate(xtal) /
270 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
271 (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
272 (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
273 (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
274
275 return 0;
276}
diff --git a/arch/arm/mach-s3c2410/s3c2410-dma.c b/arch/arm/mach-s3c2410/s3c2410-dma.c
deleted file mode 100644
index e67ba3911f11..000000000000
--- a/arch/arm/mach-s3c2410/s3c2410-dma.c
+++ /dev/null
@@ -1,161 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/s3c2410-dma.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 DMA selection
7 *
8 * http://armlinux.simtec.co.uk/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/sysdev.h>
18#include <linux/serial_core.h>
19
20#include <asm/dma.h>
21#include <asm/arch/dma.h>
22#include "dma.h"
23
24#include "cpu.h"
25
26#include <asm/arch/regs-serial.h>
27#include <asm/arch/regs-gpio.h>
28#include <asm/arch/regs-ac97.h>
29#include <asm/arch/regs-mem.h>
30#include <asm/arch/regs-lcd.h>
31#include <asm/arch/regs-sdi.h>
32#include <asm/arch/regs-iis.h>
33#include <asm/arch/regs-spi.h>
34
35static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
36 [DMACH_XD0] = {
37 .name = "xdreq0",
38 .channels[0] = S3C2410_DCON_CH0_XDREQ0 | DMA_CH_VALID,
39 },
40 [DMACH_XD1] = {
41 .name = "xdreq1",
42 .channels[1] = S3C2410_DCON_CH1_XDREQ1 | DMA_CH_VALID,
43 },
44 [DMACH_SDI] = {
45 .name = "sdi",
46 .channels[0] = S3C2410_DCON_CH0_SDI | DMA_CH_VALID,
47 .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID,
48 .channels[3] = S3C2410_DCON_CH3_SDI | DMA_CH_VALID,
49 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
50 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
51 },
52 [DMACH_SPI0] = {
53 .name = "spi0",
54 .channels[1] = S3C2410_DCON_CH1_SPI | DMA_CH_VALID,
55 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
56 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
57 },
58 [DMACH_SPI1] = {
59 .name = "spi1",
60 .channels[3] = S3C2410_DCON_CH3_SPI | DMA_CH_VALID,
61 .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
62 .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
63 },
64 [DMACH_UART0] = {
65 .name = "uart0",
66 .channels[0] = S3C2410_DCON_CH0_UART0 | DMA_CH_VALID,
67 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
68 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
69 },
70 [DMACH_UART1] = {
71 .name = "uart1",
72 .channels[1] = S3C2410_DCON_CH1_UART1 | DMA_CH_VALID,
73 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
74 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
75 },
76 [DMACH_UART2] = {
77 .name = "uart2",
78 .channels[3] = S3C2410_DCON_CH3_UART2 | DMA_CH_VALID,
79 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
80 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
81 },
82 [DMACH_TIMER] = {
83 .name = "timer",
84 .channels[0] = S3C2410_DCON_CH0_TIMER | DMA_CH_VALID,
85 .channels[2] = S3C2410_DCON_CH2_TIMER | DMA_CH_VALID,
86 .channels[3] = S3C2410_DCON_CH3_TIMER | DMA_CH_VALID,
87 },
88 [DMACH_I2S_IN] = {
89 .name = "i2s-sdi",
90 .channels[1] = S3C2410_DCON_CH1_I2SSDI | DMA_CH_VALID,
91 .channels[2] = S3C2410_DCON_CH2_I2SSDI | DMA_CH_VALID,
92 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
93 },
94 [DMACH_I2S_OUT] = {
95 .name = "i2s-sdo",
96 .channels[2] = S3C2410_DCON_CH2_I2SSDO | DMA_CH_VALID,
97 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
98 },
99 [DMACH_USB_EP1] = {
100 .name = "usb-ep1",
101 .channels[0] = S3C2410_DCON_CH0_USBEP1 | DMA_CH_VALID,
102 },
103 [DMACH_USB_EP2] = {
104 .name = "usb-ep2",
105 .channels[1] = S3C2410_DCON_CH1_USBEP2 | DMA_CH_VALID,
106 },
107 [DMACH_USB_EP3] = {
108 .name = "usb-ep3",
109 .channels[2] = S3C2410_DCON_CH2_USBEP3 | DMA_CH_VALID,
110 },
111 [DMACH_USB_EP4] = {
112 .name = "usb-ep4",
113 .channels[3] =S3C2410_DCON_CH3_USBEP4 | DMA_CH_VALID,
114 },
115};
116
117static void s3c2410_dma_select(struct s3c2410_dma_chan *chan,
118 struct s3c24xx_dma_map *map)
119{
120 chan->dcon = map->channels[chan->number] & ~DMA_CH_VALID;
121}
122
123static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
124 .select = s3c2410_dma_select,
125 .dcon_mask = 7 << 24,
126 .map = s3c2410_dma_mappings,
127 .map_size = ARRAY_SIZE(s3c2410_dma_mappings),
128};
129
130static int s3c2410_dma_add(struct sys_device *sysdev)
131{
132 return s3c24xx_dma_init_map(&s3c2410_dma_sel);
133}
134
135#if defined(CONFIG_CPU_S3C2410)
136static struct sysdev_driver s3c2410_dma_driver = {
137 .add = s3c2410_dma_add,
138};
139
140static int __init s3c2410_dma_init(void)
141{
142 return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver);
143}
144
145arch_initcall(s3c2410_dma_init);
146#endif
147
148#if defined(CONFIG_CPU_S3C2442)
149/* S3C2442 DMA contains the same selection table as the S3C2410 */
150static struct sysdev_driver s3c2442_dma_driver = {
151 .add = s3c2410_dma_add,
152};
153
154static int __init s3c2442_dma_init(void)
155{
156 return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver);
157}
158
159arch_initcall(s3c2442_dma_init);
160#endif
161
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
deleted file mode 100644
index ec3a276cc3cf..000000000000
--- a/arch/arm/mach-s3c2410/s3c2410-gpio.c
+++ /dev/null
@@ -1,71 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/s3c2410-gpio.c
2 *
3 * Copyright (c) 2004-2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 GPIO support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <linux/kernel.h>
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/interrupt.h>
27#include <linux/ioport.h>
28
29#include <asm/hardware.h>
30#include <asm/irq.h>
31#include <asm/io.h>
32
33#include <asm/arch/regs-gpio.h>
34
35int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
36 unsigned int config)
37{
38 void __iomem *reg = S3C24XX_EINFLT0;
39 unsigned long flags;
40 unsigned long val;
41
42 if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
43 return -1;
44
45 config &= 0xff;
46
47 pin -= S3C2410_GPG8;
48 reg += pin & ~3;
49
50 local_irq_save(flags);
51
52 /* update filter width and clock source */
53
54 val = __raw_readl(reg);
55 val &= ~(0xff << ((pin & 3) * 8));
56 val |= config << ((pin & 3) * 8);
57 __raw_writel(val, reg);
58
59 /* update filter enable */
60
61 val = __raw_readl(S3C24XX_EXTINT2);
62 val &= ~(1 << ((pin * 4) + 3));
63 val |= on << ((pin * 4) + 3);
64 __raw_writel(val, S3C24XX_EXTINT2);
65
66 local_irq_restore(flags);
67
68 return 0;
69}
70
71EXPORT_SYMBOL(s3c2410_gpio_irqfilter);
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c
deleted file mode 100644
index c796c9c76e78..000000000000
--- a/arch/arm/mach-s3c2410/s3c2410-irq.c
+++ /dev/null
@@ -1,48 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/s3c2410-irq.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20*/
21
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/ioport.h>
26#include <linux/ptrace.h>
27#include <linux/sysdev.h>
28
29#include "cpu.h"
30#include "pm.h"
31
32static int s3c2410_irq_add(struct sys_device *sysdev)
33{
34 return 0;
35}
36
37static struct sysdev_driver s3c2410_irq_driver = {
38 .add = s3c2410_irq_add,
39 .suspend = s3c24xx_irq_suspend,
40 .resume = s3c24xx_irq_resume,
41};
42
43static int s3c2410_irq_init(void)
44{
45 return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver);
46}
47
48arch_initcall(s3c2410_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c
deleted file mode 100644
index 8bb6e5e21f59..000000000000
--- a/arch/arm/mach-s3c2410/s3c2410-pm.c
+++ /dev/null
@@ -1,156 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/s3c2410-pm.c
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 (and compatible) Power Manager (Suspend-To-RAM) support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <linux/init.h>
24#include <linux/suspend.h>
25#include <linux/errno.h>
26#include <linux/time.h>
27#include <linux/sysdev.h>
28
29#include <asm/hardware.h>
30#include <asm/io.h>
31
32#include <asm/mach-types.h>
33
34#include <asm/arch/regs-gpio.h>
35#include <asm/arch/h1940.h>
36
37#include "cpu.h"
38#include "pm.h"
39
40#ifdef CONFIG_S3C2410_PM_DEBUG
41extern void pm_dbg(const char *fmt, ...);
42#define DBG(fmt...) pm_dbg(fmt)
43#else
44#define DBG(fmt...) printk(KERN_DEBUG fmt)
45#endif
46
47static void s3c2410_pm_prepare(void)
48{
49 /* ensure at least GSTATUS3 has the resume address */
50
51 __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
52
53 DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
54 DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
55
56 if (machine_is_h1940()) {
57 void *base = phys_to_virt(H1940_SUSPEND_CHECK);
58 unsigned long ptr;
59 unsigned long calc = 0;
60
61 /* generate check for the bootloader to check on resume */
62
63 for (ptr = 0; ptr < 0x40000; ptr += 0x400)
64 calc += __raw_readl(base+ptr);
65
66 __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
67 }
68
69 /* the RX3715 uses similar code and the same H1940 and the
70 * same offsets for resume and checksum pointers */
71
72 if (machine_is_rx3715()) {
73 void *base = phys_to_virt(H1940_SUSPEND_CHECK);
74 unsigned long ptr;
75 unsigned long calc = 0;
76
77 /* generate check for the bootloader to check on resume */
78
79 for (ptr = 0; ptr < 0x40000; ptr += 0x4)
80 calc += __raw_readl(base+ptr);
81
82 __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
83 }
84
85 if ( machine_is_aml_m5900() )
86 s3c2410_gpio_setpin(S3C2410_GPF2, 1);
87
88}
89
90static int s3c2410_pm_resume(struct sys_device *dev)
91{
92 unsigned long tmp;
93
94 /* unset the return-from-sleep flag, to ensure reset */
95
96 tmp = __raw_readl(S3C2410_GSTATUS2);
97 tmp &= S3C2410_GSTATUS2_OFFRESET;
98 __raw_writel(tmp, S3C2410_GSTATUS2);
99
100 if ( machine_is_aml_m5900() )
101 s3c2410_gpio_setpin(S3C2410_GPF2, 0);
102
103 return 0;
104}
105
106static int s3c2410_pm_add(struct sys_device *dev)
107{
108 pm_cpu_prep = s3c2410_pm_prepare;
109 pm_cpu_sleep = s3c2410_cpu_suspend;
110
111 return 0;
112}
113
114#if defined(CONFIG_CPU_S3C2410)
115static struct sysdev_driver s3c2410_pm_driver = {
116 .add = s3c2410_pm_add,
117 .resume = s3c2410_pm_resume,
118};
119
120/* register ourselves */
121
122static int __init s3c2410_pm_drvinit(void)
123{
124 return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver);
125}
126
127arch_initcall(s3c2410_pm_drvinit);
128#endif
129
130#if defined(CONFIG_CPU_S3C2440)
131static struct sysdev_driver s3c2440_pm_driver = {
132 .add = s3c2410_pm_add,
133 .resume = s3c2410_pm_resume,
134};
135
136static int __init s3c2440_pm_drvinit(void)
137{
138 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver);
139}
140
141arch_initcall(s3c2440_pm_drvinit);
142#endif
143
144#if defined(CONFIG_CPU_S3C2442)
145static struct sysdev_driver s3c2442_pm_driver = {
146 .add = s3c2410_pm_add,
147 .resume = s3c2410_pm_resume,
148};
149
150static int __init s3c2442_pm_drvinit(void)
151{
152 return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver);
153}
154
155arch_initcall(s3c2442_pm_drvinit);
156#endif
diff --git a/arch/arm/mach-s3c2410/s3c2410-sleep.S b/arch/arm/mach-s3c2410/s3c2410-sleep.S
deleted file mode 100644
index 9179a1024588..000000000000
--- a/arch/arm/mach-s3c2410/s3c2410-sleep.S
+++ /dev/null
@@ -1,68 +0,0 @@
1/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
2 *
3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 Power Manager (Suspend-To-RAM) support
7 *
8 * Based on PXA/SA1100 sleep code by:
9 * Nicolas Pitre, (c) 2002 Monta Vista Software Inc
10 * Cliff Brake, (c) 2001
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25*/
26
27#include <linux/linkage.h>
28#include <asm/assembler.h>
29#include <asm/hardware.h>
30#include <asm/arch/map.h>
31
32#include <asm/arch/regs-gpio.h>
33#include <asm/arch/regs-clock.h>
34#include <asm/arch/regs-mem.h>
35#include <asm/arch/regs-serial.h>
36
37 /* s3c2410_cpu_suspend
38 *
39 * put the cpu into sleep mode
40 */
41
42ENTRY(s3c2410_cpu_suspend)
43 @@ prepare cpu to sleep
44
45 ldr r4, =S3C2410_REFRESH
46 ldr r5, =S3C24XX_MISCCR
47 ldr r6, =S3C2410_CLKCON
48 ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB)
49 ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB)
50 ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB)
51
52 orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command
53 orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
54 orr r9, r9, #S3C2410_CLKCON_POWER @ power down command
55
56 teq pc, #0 @ first as a trial-run to load cache
57 bl s3c2410_do_sleep
58 teq r0, r0 @ now do it for real
59 b s3c2410_do_sleep @
60
61 @@ align next bit of code to cache line
62 .align 8
63s3c2410_do_sleep:
64 streq r7, [ r4 ] @ SDRAM sleep command
65 streq r8, [ r5 ] @ SDRAM power-down config
66 streq r9, [ r6 ] @ CPU sleep
671: beq 1b
68 mov pc, r14
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 4cdc0d70c19f..1a86a9803753 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -31,10 +31,10 @@
31#include <asm/arch/regs-clock.h> 31#include <asm/arch/regs-clock.h>
32#include <asm/arch/regs-serial.h> 32#include <asm/arch/regs-serial.h>
33 33
34#include "s3c2410.h" 34#include <asm/plat-s3c24xx/s3c2410.h>
35#include "cpu.h" 35#include <asm/plat-s3c24xx/cpu.h>
36#include "devs.h" 36#include <asm/plat-s3c24xx/devs.h>
37#include "clock.h" 37#include <asm/plat-s3c24xx/clock.h>
38 38
39/* Initial IO mappings */ 39/* Initial IO mappings */
40 40
@@ -110,7 +110,7 @@ static struct sys_device s3c2410_sysdev = {
110 110
111/* need to register class before we actually register the device, and 111/* need to register class before we actually register the device, and
112 * we also need to ensure that it has been initialised before any of the 112 * we also need to ensure that it has been initialised before any of the
113 * drivers even try to use it (even if not on an s3c2440 based system) 113 * drivers even try to use it (even if not on an s3c2410 based system)
114 * as a driver which may support both 2410 and 2440 may try and use it. 114 * as a driver which may support both 2410 and 2440 may try and use it.
115*/ 115*/
116 116
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
deleted file mode 100644
index fbed084f26d0..000000000000
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* arch/arm/mach-s3c2410/s3c2410.h
2 *
3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for s3c2410 machine directory
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12*/
13
14#ifdef CONFIG_CPU_S3C2410
15
16extern int s3c2410_init(void);
17
18extern void s3c2410_map_io(struct map_desc *mach_desc, int size);
19
20extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
21
22extern void s3c2410_init_clocks(int xtal);
23
24extern int s3c2410_baseclk_add(void);
25
26#else
27#define s3c2410_init_clocks NULL
28#define s3c2410_init_uarts NULL
29#define s3c2410_map_io NULL
30#define s3c2410_init NULL
31#endif
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h
deleted file mode 100644
index c6e56032a6e7..000000000000
--- a/arch/arm/mach-s3c2410/s3c2412.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/* arch/arm/mach-s3c2410/s3c2412.h
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for s3c2412 cpu support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifdef CONFIG_CPU_S3C2412
14
15extern int s3c2412_init(void);
16
17extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
18
19extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
20
21extern void s3c2412_init_clocks(int xtal);
22
23extern int s3c2412_baseclk_add(void);
24#else
25#define s3c2412_init_clocks NULL
26#define s3c2412_init_uarts NULL
27#define s3c2412_map_io NULL
28#define s3c2412_init NULL
29#endif
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h
deleted file mode 100644
index dcd316076c59..000000000000
--- a/arch/arm/mach-s3c2410/s3c2440.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/* arch/arm/mach-s3c2410/s3c2440.h
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for s3c2440 cpu support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifdef CONFIG_CPU_S3C2440
14extern int s3c2440_init(void);
15#else
16#define s3c2440_init NULL
17#endif
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h
deleted file mode 100644
index 0ae37d24866c..000000000000
--- a/arch/arm/mach-s3c2410/s3c2442.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/* arch/arm/mach-s3c2410/s3c2442.h
2 *
3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for s3c2442 cpu support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#ifdef CONFIG_CPU_S3C2442
14extern int s3c2442_init(void);
15#else
16#define s3c2442_init NULL
17#endif
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 2018c2e1dcc5..637aaba65390 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/sleep.S 1/* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S
2 * 2 *
3 * Copyright (c) 2004 Simtec Electronics 3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -34,126 +34,35 @@
34#include <asm/arch/regs-mem.h> 34#include <asm/arch/regs-mem.h>
35#include <asm/arch/regs-serial.h> 35#include <asm/arch/regs-serial.h>
36 36
37/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not 37 /* s3c2410_cpu_suspend
38 * reset the UART configuration, only enable if you really need this!
39*/
40//#define CONFIG_DEBUG_RESUME
41
42 .text
43
44 /* s3c2410_cpu_save
45 *
46 * save enough of the CPU state to allow us to re-start
47 * pm.c code. as we store items like the sp/lr, we will
48 * end up returning from this function when the cpu resumes
49 * so the return value is set to mark this.
50 *
51 * This arangement means we avoid having to flush the cache
52 * from this code.
53 *
54 * entry:
55 * r0 = pointer to save block
56 *
57 * exit:
58 * r0 = 0 => we stored everything
59 * 1 => resumed from sleep
60 */
61
62ENTRY(s3c2410_cpu_save)
63 stmfd sp!, { r4 - r12, lr }
64
65 @@ store co-processor registers
66
67 mrc p15, 0, r4, c15, c1, 0 @ CP access register
68 mrc p15, 0, r5, c13, c0, 0 @ PID
69 mrc p15, 0, r6, c3, c0, 0 @ Domain ID
70 mrc p15, 0, r7, c2, c0, 0 @ translation table base address
71 mrc p15, 0, r8, c1, c0, 0 @ control register
72
73 stmia r0, { r4 - r13 }
74
75 mov r0, #0
76 ldmfd sp, { r4 - r12, pc }
77
78 @@ return to the caller, after having the MMU
79 @@ turned on, this restores the last bits from the
80 @@ stack
81resume_with_mmu:
82 mov r0, #1
83 ldmfd sp!, { r4 - r12, pc }
84
85 .ltorg
86
87 @@ the next bits sit in the .data segment, even though they
88 @@ happen to be code... the s3c2410_sleep_save_phys needs to be
89 @@ accessed by the resume code before it can restore the MMU.
90 @@ This means that the variable has to be close enough for the
91 @@ code to read it... since the .text segment needs to be RO,
92 @@ the data segment can be the only place to put this code.
93
94 .data
95
96 .global s3c2410_sleep_save_phys
97s3c2410_sleep_save_phys:
98 .word 0
99
100 /* s3c2410_cpu_resume
101 * 38 *
102 * resume code entry for bootloader to call 39 * put the cpu into sleep mode
103 *
104 * we must put this code here in the data segment as we have no
105 * other way of restoring the stack pointer after sleep, and we
106 * must not write to the code segment (code is read-only)
107 */ 40 */
108 41
109ENTRY(s3c2410_cpu_resume) 42ENTRY(s3c2410_cpu_suspend)
110 mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE 43 @@ prepare cpu to sleep
111 msr cpsr_c, r0 44
112 45 ldr r4, =S3C2410_REFRESH
113 @@ load UART to allow us to print the two characters for 46 ldr r5, =S3C24XX_MISCCR
114 @@ resume debug 47 ldr r6, =S3C2410_CLKCON
115 48 ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB)
116 mov r2, #S3C24XX_PA_UART & 0xff000000 49 ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB)
117 orr r2, r2, #S3C24XX_PA_UART & 0xff000 50 ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB)
118 51
119#if 0 52 orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command
120 /* SMDK2440 LED set */ 53 orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals
121 mov r14, #S3C24XX_PA_GPIO 54 orr r9, r9, #S3C2410_CLKCON_POWER @ power down command
122 ldr r12, [ r14, #0x54 ] 55
123 bic r12, r12, #3<<4 56 teq pc, #0 @ first as a trial-run to load cache
124 orr r12, r12, #1<<7 57 bl s3c2410_do_sleep
125 str r12, [ r14, #0x54 ] 58 teq r0, r0 @ now do it for real
126#endif 59 b s3c2410_do_sleep @
127 60
128#ifdef CONFIG_DEBUG_RESUME 61 @@ align next bit of code to cache line
129 mov r3, #'L' 62 .align 5
130 strb r3, [ r2, #S3C2410_UTXH ] 63s3c2410_do_sleep:
1311001: 64 streq r7, [ r4 ] @ SDRAM sleep command
132 ldrb r14, [ r3, #S3C2410_UTRSTAT ] 65 streq r8, [ r5 ] @ SDRAM power-down config
133 tst r14, #S3C2410_UTRSTAT_TXE 66 streq r9, [ r6 ] @ CPU sleep
134 beq 1001b 671: beq 1b
135#endif /* CONFIG_DEBUG_RESUME */ 68 mov pc, r14
136
137 mov r1, #0
138 mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
139 mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
140
141 ldr r0, s3c2410_sleep_save_phys @ address of restore block
142 ldmia r0, { r4 - r13 }
143
144 mcr p15, 0, r4, c15, c1, 0 @ CP access register
145 mcr p15, 0, r5, c13, c0, 0 @ PID
146 mcr p15, 0, r6, c3, c0, 0 @ Domain ID
147 mcr p15, 0, r7, c2, c0, 0 @ translation table base
148
149#ifdef CONFIG_DEBUG_RESUME
150 mov r3, #'R'
151 strb r3, [ r2, #S3C2410_UTXH ]
152#endif
153
154 ldr r2, =resume_with_mmu
155 mcr p15, 0, r8, c1, c0, 0 @ turn on MMU, etc
156 nop @ second-to-last before mmu
157 mov pc, r2 @ go back to virtual address
158
159 .ltorg
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 22b0e1cdd4bf..bcd562ac1d3d 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -35,7 +35,7 @@
35#include <asm/io.h> 35#include <asm/io.h>
36#include <asm/irq.h> 36#include <asm/irq.h>
37 37
38#include "devs.h" 38#include <asm/plat-s3c24xx/devs.h>
39#include "usb-simtec.h" 39#include "usb-simtec.h"
40 40
41/* control power and monitor over-current events on various Simtec 41/* control power and monitor over-current events on various Simtec
diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig
new file mode 100644
index 000000000000..befc5fdbb613
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Kconfig
@@ -0,0 +1,58 @@
1# arch/arm/mach-s3c2412/Kconfig
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7config CPU_S3C2412
8 bool
9 depends on ARCH_S3C2410
10 select S3C2412_PM if PM
11 select S3C2412_DMA if S3C2410_DMA
12 help
13 Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
14
15config CPU_S3C2412_ONLY
16 bool
17 depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
18 !CPU_S3C2440 && !CPU_S3C2442 && !CPU_S3C2443 && CPU_S3C2412
19 default y if CPU_S3C2412
20
21config S3C2412_DMA
22 bool
23 depends on CPU_S3C2412
24 help
25 Internal config node for S3C2412 DMA support
26
27config S3C2412_PM
28 bool
29 help
30 Internal config node to apply S3C2412 power management
31
32
33menu "S3C2412 Machines"
34
35config MACH_SMDK2413
36 bool "SMDK2413"
37 select CPU_S3C2412
38 select MACH_S3C2413
39 select MACH_SMDK
40 help
41 Say Y here if you are using an SMDK2413
42
43config MACH_S3C2413
44 bool
45 help
46 Internal node for S3C2413 version of SMDK2413, so that
47 machine_is_s3c2413() will work when MACH_SMDK2413 is
48 selected
49
50config MACH_VSTMS
51 bool "VMSTMS"
52 select CPU_S3C2412
53 help
54 Say Y here if you are using an VSTMS board
55
56
57endmenu
58
diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile
new file mode 100644
index 000000000000..f8e011691b31
--- /dev/null
+++ b/arch/arm/mach-s3c2412/Makefile
@@ -0,0 +1,21 @@
1# arch/arm/mach-s3c2412/Makefile
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7obj-y :=
8obj-m :=
9obj-n :=
10obj- :=
11
12obj-$(CONFIG_CPU_S3C2412) += s3c2412.o
13obj-$(CONFIG_CPU_S3C2412) += irq.o
14obj-$(CONFIG_CPU_S3C2412) += clock.o
15obj-$(CONFIG_S3C2412_DMA) += dma.o
16obj-$(CONFIG_S3C2412_PM) += pm.o
17
18# Machine support
19
20obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o
21obj-$(CONFIG_MACH_VSTMS) += mach-vstms.o
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2412/clock.c
index 8f94ad83901d..6a8e4448770b 100644
--- a/arch/arm/mach-s3c2410/s3c2412-clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c 1/* linux/arch/arm/mach-s3c2412/clock.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -41,9 +41,9 @@
41#include <asm/arch/regs-clock.h> 41#include <asm/arch/regs-clock.h>
42#include <asm/arch/regs-gpio.h> 42#include <asm/arch/regs-gpio.h>
43 43
44#include "s3c2412.h" 44#include <asm/plat-s3c24xx/s3c2412.h>
45#include "clock.h" 45#include <asm/plat-s3c24xx/clock.h>
46#include "cpu.h" 46#include <asm/plat-s3c24xx/cpu.h>
47 47
48/* We currently have to assume that the system is running 48/* We currently have to assume that the system is running
49 * from the XTPll input, and that all ***REFCLKs are being 49 * from the XTPll input, and that all ***REFCLKs are being
diff --git a/arch/arm/mach-s3c2410/s3c2412-dma.c b/arch/arm/mach-s3c2412/dma.c
index 138f726ac6bf..d0f4695c09d9 100644
--- a/arch/arm/mach-s3c2410/s3c2412-dma.c
+++ b/arch/arm/mach-s3c2412/dma.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2412-dma.c 1/* linux/arch/arm/mach-s3c2412/dma.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -21,8 +21,8 @@
21#include <asm/arch/dma.h> 21#include <asm/arch/dma.h>
22#include <asm/io.h> 22#include <asm/io.h>
23 23
24#include "dma.h" 24#include <asm/plat-s3c24xx/dma.h>
25#include "cpu.h" 25#include <asm/plat-s3c24xx/cpu.h>
26 26
27#include <asm/arch/regs-serial.h> 27#include <asm/arch/regs-serial.h>
28#include <asm/arch/regs-gpio.h> 28#include <asm/arch/regs-gpio.h>
@@ -146,6 +146,7 @@ static struct s3c24xx_dma_selection __initdata s3c2412_dma_sel = {
146 146
147static int s3c2412_dma_add(struct sys_device *sysdev) 147static int s3c2412_dma_add(struct sys_device *sysdev)
148{ 148{
149 s3c2410_dma_init();
149 return s3c24xx_dma_init_map(&s3c2412_dma_sel); 150 return s3c24xx_dma_init_map(&s3c2412_dma_sel);
150} 151}
151 152
diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2412/irq.c
index ffcc30b23a80..e89dbdcb1b7b 100644
--- a/arch/arm/mach-s3c2410/s3c2412-irq.c
+++ b/arch/arm/mach-s3c2412/irq.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c 1/* linux/arch/arm/mach-s3c2412/irq.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
35#include <asm/arch/regs-irq.h> 35#include <asm/arch/regs-irq.h>
36#include <asm/arch/regs-gpio.h> 36#include <asm/arch/regs-gpio.h>
37 37
38#include "cpu.h" 38#include <asm/plat-s3c24xx/cpu.h>
39#include "irq.h" 39#include <asm/plat-s3c24xx/irq.h>
40#include "pm.h" 40#include <asm/plat-s3c24xx/pm.h>
41 41
42/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by 42/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
43 * having them turn up in both the INT* and the EINT* registers. Whilst 43 * having them turn up in both the INT* and the EINT* registers. Whilst
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index 4f89abd7a6df..b5befce6c8d3 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c 1/* linux/arch/arm/mach-s3c2412/mach-smdk2413.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -37,15 +37,16 @@
37#include <asm/arch/regs-lcd.h> 37#include <asm/arch/regs-lcd.h>
38 38
39#include <asm/arch/idle.h> 39#include <asm/arch/idle.h>
40#include <asm/arch/udc.h>
40#include <asm/arch/fb.h> 41#include <asm/arch/fb.h>
41 42
42#include "s3c2410.h" 43#include <asm/plat-s3c24xx/s3c2410.h>
43#include "s3c2412.h" 44#include <asm/plat-s3c24xx/s3c2412.h>
44#include "clock.h" 45#include <asm/plat-s3c24xx/clock.h>
45#include "devs.h" 46#include <asm/plat-s3c24xx/devs.h>
46#include "cpu.h" 47#include <asm/plat-s3c24xx/cpu.h>
47 48
48#include "common-smdk.h" 49#include <asm/plat-s3c24xx/common-smdk.h>
49 50
50static struct map_desc smdk2413_iodesc[] __initdata = { 51static struct map_desc smdk2413_iodesc[] __initdata = {
51}; 52};
@@ -75,12 +76,38 @@ static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
75 } 76 }
76}; 77};
77 78
79static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd)
80{
81 printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
82
83 switch (cmd)
84 {
85 case S3C2410_UDC_P_ENABLE :
86 s3c2410_gpio_setpin(S3C2410_GPF2, 1);
87 break;
88 case S3C2410_UDC_P_DISABLE :
89 s3c2410_gpio_setpin(S3C2410_GPF2, 0);
90 break;
91 case S3C2410_UDC_P_RESET :
92 break;
93 default:
94 break;
95 }
96}
97
98
99static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = {
100 .udc_command = smdk2413_udc_pullup,
101};
102
103
78static struct platform_device *smdk2413_devices[] __initdata = { 104static struct platform_device *smdk2413_devices[] __initdata = {
79 &s3c_device_usb, 105 &s3c_device_usb,
80 //&s3c_device_lcd, 106 //&s3c_device_lcd,
81 &s3c_device_wdt, 107 &s3c_device_wdt,
82 &s3c_device_i2c, 108 &s3c_device_i2c,
83 &s3c_device_iis, 109 &s3c_device_iis,
110 &s3c_device_usbgadget,
84}; 111};
85 112
86static struct s3c24xx_board smdk2413_board __initdata = { 113static struct s3c24xx_board smdk2413_board __initdata = {
@@ -109,7 +136,19 @@ static void __init smdk2413_map_io(void)
109} 136}
110 137
111static void __init smdk2413_machine_init(void) 138static void __init smdk2413_machine_init(void)
112{ 139{ /* Turn off suspend on both USB ports, and switch the
140 * selectable USB port to USB device mode. */
141
142 s3c2410_gpio_setpin(S3C2410_GPF2, 0);
143 s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPIO_OUTPUT);
144
145 s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
146 S3C2410_MISCCR_USBSUSPND0 |
147 S3C2410_MISCCR_USBSUSPND1, 0x0);
148
149
150 s3c24xx_udc_set_platdata(&smdk2413_udc_cfg);
151
113 smdk_machine_init(); 152 smdk_machine_init();
114} 153}
115 154
@@ -126,6 +165,19 @@ MACHINE_START(S3C2413, "S3C2413")
126 .timer = &s3c24xx_timer, 165 .timer = &s3c24xx_timer,
127MACHINE_END 166MACHINE_END
128 167
168MACHINE_START(SMDK2412, "SMDK2412")
169 /* Maintainer: Ben Dooks <ben@fluff.org> */
170 .phys_io = S3C2410_PA_UART,
171 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
172 .boot_params = S3C2410_SDRAM_PA + 0x100,
173
174 .fixup = smdk2413_fixup,
175 .init_irq = s3c24xx_init_irq,
176 .map_io = smdk2413_map_io,
177 .init_machine = smdk2413_machine_init,
178 .timer = &s3c24xx_timer,
179MACHINE_END
180
129MACHINE_START(SMDK2413, "SMDK2413") 181MACHINE_START(SMDK2413, "SMDK2413")
130 /* Maintainer: Ben Dooks <ben@fluff.org> */ 182 /* Maintainer: Ben Dooks <ben@fluff.org> */
131 .phys_io = S3C2410_PA_UART, 183 .phys_io = S3C2410_PA_UART,
diff --git a/arch/arm/mach-s3c2410/mach-vstms.c b/arch/arm/mach-s3c2412/mach-vstms.c
index 0360e1055bcd..4231b549d797 100644
--- a/arch/arm/mach-s3c2410/mach-vstms.c
+++ b/arch/arm/mach-s3c2412/mach-vstms.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/mach-vstms.c 1/* linux/arch/arm/mach-s3c2412/mach-vstms.c
2 * 2 *
3 * (C) 2006 Thomas Gleixner <tglx@linutronix.de> 3 * (C) 2006 Thomas Gleixner <tglx@linutronix.de>
4 * 4 *
@@ -28,7 +28,6 @@
28#include <asm/mach/irq.h> 28#include <asm/mach/irq.h>
29 29
30#include <asm/hardware.h> 30#include <asm/hardware.h>
31#include <asm/hardware/iomd.h>
32#include <asm/setup.h> 31#include <asm/setup.h>
33#include <asm/io.h> 32#include <asm/io.h>
34#include <asm/irq.h> 33#include <asm/irq.h>
@@ -43,11 +42,11 @@
43 42
44#include <asm/arch/nand.h> 43#include <asm/arch/nand.h>
45 44
46#include "s3c2410.h" 45#include <asm/plat-s3c24xx/s3c2410.h>
47#include "s3c2412.h" 46#include <asm/plat-s3c24xx/s3c2412.h>
48#include "clock.h" 47#include <asm/plat-s3c24xx/clock.h>
49#include "devs.h" 48#include <asm/plat-s3c24xx/devs.h>
50#include "cpu.h" 49#include <asm/plat-s3c24xx/cpu.h>
51 50
52 51
53static struct map_desc vstms_iodesc[] __initdata = { 52static struct map_desc vstms_iodesc[] __initdata = {
diff --git a/arch/arm/mach-s3c2410/s3c2412-pm.c b/arch/arm/mach-s3c2412/pm.c
index 19b63322d259..8988dac388a9 100644
--- a/arch/arm/mach-s3c2410/s3c2412-pm.c
+++ b/arch/arm/mach-s3c2412/pm.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2412-pm.c 1/* linux/arch/arm/mach-s3c2412/pm.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -28,10 +28,10 @@
28#include <asm/arch/regs-gpio.h> 28#include <asm/arch/regs-gpio.h>
29#include <asm/arch/regs-dsc.h> 29#include <asm/arch/regs-dsc.h>
30 30
31#include "cpu.h" 31#include <asm/plat-s3c24xx/cpu.h>
32#include "pm.h" 32#include <asm/plat-s3c24xx/pm.h>
33 33
34#include "s3c2412.h" 34#include <asm/plat-s3c24xx/s3c2412.h>
35 35
36static void s3c2412_cpu_suspend(void) 36static void s3c2412_cpu_suspend(void)
37{ 37{
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c
index 2f651a811ecd..aafe0bc593f1 100644
--- a/arch/arm/mach-s3c2410/s3c2412.c
+++ b/arch/arm/mach-s3c2412/s3c2412.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2412.c 1/* linux/arch/arm/mach-s3c2412/s3c2412.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -38,11 +38,11 @@
38#include <asm/arch/regs-gpioj.h> 38#include <asm/arch/regs-gpioj.h>
39#include <asm/arch/regs-dsc.h> 39#include <asm/arch/regs-dsc.h>
40 40
41#include "s3c2412.h" 41#include <asm/plat-s3c24xx/s3c2412.h>
42#include "cpu.h" 42#include <asm/plat-s3c24xx/cpu.h>
43#include "devs.h" 43#include <asm/plat-s3c24xx/devs.h>
44#include "clock.h" 44#include <asm/plat-s3c24xx/clock.h>
45#include "pm.h" 45#include <asm/plat-s3c24xx/pm.h>
46 46
47#ifndef CONFIG_CPU_S3C2412_ONLY 47#ifndef CONFIG_CPU_S3C2412_ONLY
48void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; 48void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig
new file mode 100644
index 000000000000..e3bfda098c0f
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Kconfig
@@ -0,0 +1,71 @@
1# arch/arm/mach-s3c2440/Kconfig
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7config CPU_S3C2440
8 bool
9 depends on ARCH_S3C2410
10 select S3C2410_CLOCK
11 select S3C2410_PM if PM
12 select S3C2410_GPIO
13 select S3C2440_DMA if S3C2410_DMA
14 select CPU_S3C244X
15 help
16 Support for S3C2440 Samsung Mobile CPU based systems.
17
18config S3C2440_DMA
19 bool
20 depends on ARCH_S3C2410 && CPU_S3C24405B
21 help
22 Support for S3C2440 specific DMA code5A
23
24
25menu "S3C2440 Machines"
26
27config MACH_ANUBIS
28 bool "Simtec Electronics ANUBIS"
29 select CPU_S3C2440
30 select PM_SIMTEC if PM
31 help
32 Say Y here if you are using the Simtec Electronics ANUBIS
33 development system
34
35config MACH_OSIRIS
36 bool "Simtec IM2440D20 (OSIRIS) module"
37 select CPU_S3C2440
38 select PM_SIMTEC if PM
39 help
40 Say Y here if you are using the Simtec IM2440D20 module, also
41 known as the Osiris.
42
43config MACH_RX3715
44 bool "HP iPAQ rx3715"
45 select CPU_S3C2440
46 select PM_H1940 if PM
47 help
48 Say Y here if you are using the HP iPAQ rx3715.
49
50config ARCH_S3C2440
51 bool "SMDK2440"
52 select CPU_S3C2440
53 select MACH_SMDK
54 help
55 Say Y here if you are using the SMDK2440.
56
57config MACH_NEXCODER_2440
58 bool "NexVision NEXCODER 2440 Light Board"
59 select CPU_S3C2440
60 help
61 Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
62
63config SMDK2440_CPU2440
64 bool "SMDK2440 with S3C2440 CPU module"
65 depends on ARCH_S3C2440
66 default y if ARCH_S3C2440
67 select CPU_S3C2440
68
69
70endmenu
71
diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile
new file mode 100644
index 000000000000..c81ed6248dcb
--- /dev/null
+++ b/arch/arm/mach-s3c2440/Makefile
@@ -0,0 +1,23 @@
1# arch/arm/mach-s3c2440/Makefile
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7obj-y :=
8obj-m :=
9obj-n :=
10obj- :=
11
12obj-$(CONFIG_CPU_S3C2440) += s3c2440.o dsc.o
13obj-$(CONFIG_CPU_S3C2440) += irq.o
14obj-$(CONFIG_CPU_S3C2440) += clock.o
15obj-$(CONFIG_S3C2440_DMA) += dma.o
16
17# Machine support
18
19obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o
20obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o
21obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o
22obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
23obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2440/clock.c
index ba13c1d079d1..79e2ea4adaf3 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2440-clock.c 1/* linux/arch/arm/mach-s3c2440/clock.c
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2004-2005 Simtec Electronics
4 * http://armlinux.simtec.co.uk/ 4 * http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
41 41
42#include <asm/arch/regs-clock.h> 42#include <asm/arch/regs-clock.h>
43 43
44#include "clock.h" 44#include <asm/plat-s3c24xx/clock.h>
45#include "cpu.h" 45#include <asm/plat-s3c24xx/cpu.h>
46 46
47/* S3C2440 extended clock support */ 47/* S3C2440 extended clock support */
48 48
diff --git a/arch/arm/mach-s3c2410/s3c2440-dma.c b/arch/arm/mach-s3c2440/dma.c
index 47b861b9443d..cd035a3ec878 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dma.c
+++ b/arch/arm/mach-s3c2440/dma.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2440-dma.c 1/* linux/arch/arm/mach-s3c2440/dma.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -19,9 +19,9 @@
19 19
20#include <asm/dma.h> 20#include <asm/dma.h>
21#include <asm/arch/dma.h> 21#include <asm/arch/dma.h>
22#include "dma.h"
23 22
24#include "cpu.h" 23#include <asm/plat-s3c24xx/dma.h>
24#include <asm/plat-s3c24xx/cpu.h>
25 25
26#include <asm/arch/regs-serial.h> 26#include <asm/arch/regs-serial.h>
27#include <asm/arch/regs-gpio.h> 27#include <asm/arch/regs-gpio.h>
@@ -147,8 +147,53 @@ static struct s3c24xx_dma_selection __initdata s3c2440_dma_sel = {
147 .map_size = ARRAY_SIZE(s3c2440_dma_mappings), 147 .map_size = ARRAY_SIZE(s3c2440_dma_mappings),
148}; 148};
149 149
150static struct s3c24xx_dma_order __initdata s3c2440_dma_order = {
151 .channels = {
152 [DMACH_SDI] = {
153 .list = {
154 [0] = 3 | DMA_CH_VALID,
155 [1] = 2 | DMA_CH_VALID,
156 [2] = 1 | DMA_CH_VALID,
157 [3] = 0 | DMA_CH_VALID,
158 },
159 },
160 [DMACH_I2S_IN] = {
161 .list = {
162 [0] = 1 | DMA_CH_VALID,
163 [1] = 2 | DMA_CH_VALID,
164 },
165 },
166 [DMACH_I2S_OUT] = {
167 .list = {
168 [0] = 2 | DMA_CH_VALID,
169 [1] = 1 | DMA_CH_VALID,
170 },
171 },
172 [DMACH_PCM_IN] = {
173 .list = {
174 [0] = 2 | DMA_CH_VALID,
175 [1] = 1 | DMA_CH_VALID,
176 },
177 },
178 [DMACH_PCM_OUT] = {
179 .list = {
180 [0] = 1 | DMA_CH_VALID,
181 [1] = 3 | DMA_CH_VALID,
182 },
183 },
184 [DMACH_MIC_IN] = {
185 .list = {
186 [0] = 3 | DMA_CH_VALID,
187 [1] = 2 | DMA_CH_VALID,
188 },
189 },
190 },
191};
192
150static int s3c2440_dma_add(struct sys_device *sysdev) 193static int s3c2440_dma_add(struct sys_device *sysdev)
151{ 194{
195 s3c2410_dma_init();
196 s3c24xx_dma_order_set(&s3c2440_dma_order);
152 return s3c24xx_dma_init_map(&s3c2440_dma_sel); 197 return s3c24xx_dma_init_map(&s3c2440_dma_sel);
153} 198}
154 199
diff --git a/arch/arm/mach-s3c2410/s3c2440-dsc.c b/arch/arm/mach-s3c2440/dsc.c
index c92ea66ba45e..2995ff5681bb 100644
--- a/arch/arm/mach-s3c2410/s3c2440-dsc.c
+++ b/arch/arm/mach-s3c2440/dsc.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2440-dsc.c 1/* linux/arch/arm/mach-s3c2440/dsc.c
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -27,8 +27,8 @@
27#include <asm/arch/regs-gpio.h> 27#include <asm/arch/regs-gpio.h>
28#include <asm/arch/regs-dsc.h> 28#include <asm/arch/regs-dsc.h>
29 29
30#include "cpu.h" 30#include <asm/plat-s3c24xx/cpu.h>
31#include "s3c2440.h" 31#include <asm/plat-s3c24xx/s3c2440.h>
32 32
33int s3c2440_set_dsc(unsigned int pin, unsigned int value) 33int s3c2440_set_dsc(unsigned int pin, unsigned int value)
34{ 34{
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2440/irq.c
index 1ba19b27ab05..1069d13d8c57 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2440/irq.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c 1/* linux/arch/arm/mach-s3c2440/irq.c
2 * 2 *
3 * Copyright (c) 2003,2004 Simtec Electronics 3 * Copyright (c) 2003,2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
35#include <asm/arch/regs-irq.h> 35#include <asm/arch/regs-irq.h>
36#include <asm/arch/regs-gpio.h> 36#include <asm/arch/regs-gpio.h>
37 37
38#include "cpu.h" 38#include <asm/plat-s3c24xx/cpu.h>
39#include "pm.h" 39#include <asm/plat-s3c24xx/pm.h>
40#include "irq.h" 40#include <asm/plat-s3c24xx/irq.h>
41 41
42/* WDT/AC97 */ 42/* WDT/AC97 */
43 43
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index 0fad0c2fe07b..3f0288eb1ed5 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/mach-anubis.c 1/* linux/arch/arm/mach-s3c2440/mach-anubis.c
2 * 2 *
3 * Copyright (c) 2003-2005 Simtec Electronics 3 * Copyright (c) 2003-2005 Simtec Electronics
4 * http://armlinux.simtec.co.uk/ 4 * http://armlinux.simtec.co.uk/
@@ -42,9 +42,9 @@
42#include <linux/mtd/nand_ecc.h> 42#include <linux/mtd/nand_ecc.h>
43#include <linux/mtd/partitions.h> 43#include <linux/mtd/partitions.h>
44 44
45#include "clock.h" 45#include <asm/plat-s3c24xx/clock.h>
46#include "devs.h" 46#include <asm/plat-s3c24xx/devs.h>
47#include "cpu.h" 47#include <asm/plat-s3c24xx/cpu.h>
48 48
49#define COPYRIGHT ", (c) 2005 Simtec Electronics" 49#define COPYRIGHT ", (c) 2005 Simtec Electronics"
50 50
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c
index d6dfdad8c90b..6d551d88330b 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2440/mach-nexcoder.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/mach-nexcoder.c 1/* linux/arch/arm/mach-s3c2440/mach-nexcoder.c
2 * 2 *
3 * Copyright (c) 2004 Nex Vision 3 * Copyright (c) 2004 Nex Vision
4 * Guillaume GOURAT <guillaume.gourat@nexvision.tv> 4 * Guillaume GOURAT <guillaume.gourat@nexvision.tv>
@@ -38,11 +38,11 @@
38#include <asm/arch/regs-gpio.h> 38#include <asm/arch/regs-gpio.h>
39#include <asm/arch/regs-serial.h> 39#include <asm/arch/regs-serial.h>
40 40
41#include "s3c2410.h" 41#include <asm/plat-s3c24xx/s3c2410.h>
42#include "s3c2440.h" 42#include <asm/plat-s3c24xx/s3c2440.h>
43#include "clock.h" 43#include <asm/plat-s3c24xx/clock.h>
44#include "devs.h" 44#include <asm/plat-s3c24xx/devs.h>
45#include "cpu.h" 45#include <asm/plat-s3c24xx/cpu.h>
46 46
47static struct map_desc nexcoder_iodesc[] __initdata = { 47static struct map_desc nexcoder_iodesc[] __initdata = {
48 /* nothing here yet */ 48 /* nothing here yet */
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 37b40850c9b9..2ed8e51f20c8 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/mach-osiris.c 1/* linux/arch/arm/mach-s3c2440/mach-osiris.c
2 * 2 *
3 * Copyright (c) 2005 Simtec Electronics 3 * Copyright (c) 2005 Simtec Electronics
4 * http://armlinux.simtec.co.uk/ 4 * http://armlinux.simtec.co.uk/
@@ -41,9 +41,9 @@
41#include <linux/mtd/nand_ecc.h> 41#include <linux/mtd/nand_ecc.h>
42#include <linux/mtd/partitions.h> 42#include <linux/mtd/partitions.h>
43 43
44#include "clock.h" 44#include <asm/plat-s3c24xx/clock.h>
45#include "devs.h" 45#include <asm/plat-s3c24xx/devs.h>
46#include "cpu.h" 46#include <asm/plat-s3c24xx/cpu.h>
47 47
48/* onboard perihpheral map */ 48/* onboard perihpheral map */
49 49
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c
index ecbcdf79d739..480ccde63fb4 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2440/mach-rx3715.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/mach-rx3715.c 1/* linux/arch/arm/mach-s3c2440/mach-rx3715.c
2 * 2 *
3 * Copyright (c) 2003,2004 Simtec Electronics 3 * Copyright (c) 2003,2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -33,7 +33,6 @@
33#include <asm/mach/irq.h> 33#include <asm/mach/irq.h>
34 34
35#include <asm/hardware.h> 35#include <asm/hardware.h>
36#include <asm/hardware/iomd.h>
37#include <asm/io.h> 36#include <asm/io.h>
38#include <asm/irq.h> 37#include <asm/irq.h>
39#include <asm/mach-types.h> 38#include <asm/mach-types.h>
@@ -46,10 +45,10 @@
46#include <asm/arch/nand.h> 45#include <asm/arch/nand.h>
47#include <asm/arch/fb.h> 46#include <asm/arch/fb.h>
48 47
49#include "clock.h" 48#include <asm/plat-s3c24xx/clock.h>
50#include "devs.h" 49#include <asm/plat-s3c24xx/devs.h>
51#include "cpu.h" 50#include <asm/plat-s3c24xx/cpu.h>
52#include "pm.h" 51#include <asm/plat-s3c24xx/pm.h>
53 52
54static struct map_desc rx3715_iodesc[] __initdata = { 53static struct map_desc rx3715_iodesc[] __initdata = {
55 /* dump ISA space somewhere unused */ 54 /* dump ISA space somewhere unused */
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c
index 2b61f4ed1da4..c17eb5b1f6b4 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2440/mach-smdk2440.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/mach-smdk2440.c 1/* linux/arch/arm/mach-s3c2440/mach-smdk2440.c
2 * 2 *
3 * Copyright (c) 2004,2005 Simtec Electronics 3 * Copyright (c) 2004,2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -27,12 +27,10 @@
27#include <asm/mach/irq.h> 27#include <asm/mach/irq.h>
28 28
29#include <asm/hardware.h> 29#include <asm/hardware.h>
30#include <asm/hardware/iomd.h>
31#include <asm/io.h> 30#include <asm/io.h>
32#include <asm/irq.h> 31#include <asm/irq.h>
33#include <asm/mach-types.h> 32#include <asm/mach-types.h>
34 33
35//#include <asm/debug-ll.h>
36#include <asm/arch/regs-serial.h> 34#include <asm/arch/regs-serial.h>
37#include <asm/arch/regs-gpio.h> 35#include <asm/arch/regs-gpio.h>
38#include <asm/arch/regs-lcd.h> 36#include <asm/arch/regs-lcd.h>
@@ -40,13 +38,13 @@
40#include <asm/arch/idle.h> 38#include <asm/arch/idle.h>
41#include <asm/arch/fb.h> 39#include <asm/arch/fb.h>
42 40
43#include "s3c2410.h" 41#include <asm/plat-s3c24xx/s3c2410.h>
44#include "s3c2440.h" 42#include <asm/plat-s3c24xx/s3c2440.h>
45#include "clock.h" 43#include <asm/plat-s3c24xx/clock.h>
46#include "devs.h" 44#include <asm/plat-s3c24xx/devs.h>
47#include "cpu.h" 45#include <asm/plat-s3c24xx/cpu.h>
48 46
49#include "common-smdk.h" 47#include <asm/plat-s3c24xx/common-smdk.h>
50 48
51static struct map_desc smdk2440_iodesc[] __initdata = { 49static struct map_desc smdk2440_iodesc[] __initdata = {
52 /* ISA IO Space map (memory space selected by A24) */ 50 /* ISA IO Space map (memory space selected by A24) */
@@ -144,6 +142,7 @@ static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {
144#endif 142#endif
145 143
146 .lpcsel = ((0xCE6) & ~7) | 1<<4, 144 .lpcsel = ((0xCE6) & ~7) | 1<<4,
145 .type = S3C2410_LCDCON1_TFT16BPP,
147 146
148 .width = 240, 147 .width = 240,
149 .height = 320, 148 .height = 320,
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c
index 344eb27cca48..90e1da61fbc3 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2440/s3c2440.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2440.c 1/* linux/arch/arm/mach-s3c2440/s3c2440.c
2 * 2 *
3 * Copyright (c) 2004-2006 Simtec Electronics 3 * Copyright (c) 2004-2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -29,9 +29,9 @@
29#include <asm/io.h> 29#include <asm/io.h>
30#include <asm/irq.h> 30#include <asm/irq.h>
31 31
32#include "s3c2440.h" 32#include <asm/plat-s3c24xx/s3c2440.h>
33#include "devs.h" 33#include <asm/plat-s3c24xx/devs.h>
34#include "cpu.h" 34#include <asm/plat-s3c24xx/cpu.h>
35 35
36static struct sys_device s3c2440_sysdev = { 36static struct sys_device s3c2440_sysdev = {
37 .cls = &s3c2440_sysclass, 37 .cls = &s3c2440_sysclass,
diff --git a/arch/arm/mach-s3c2442/Kconfig b/arch/arm/mach-s3c2442/Kconfig
new file mode 100644
index 000000000000..bf8d87abfab3
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Kconfig
@@ -0,0 +1,27 @@
1# arch/arm/mach-s3c2442/Kconfig
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7config CPU_S3C2442
8 bool
9 depends on ARCH_S3C2420
10 select S3C2410_CLOCK
11 select S3C2410_GPIO
12 select S3C2410_PM if PM
13 select CPU_S3C244X
14 help
15 Support for S3C2442 Samsung Mobile CPU based systems.
16
17
18menu "S3C2442 Machines"
19
20config SMDK2440_CPU2442
21 bool "SMDM2440 with S3C2442 CPU module"
22 depends on ARCH_S3C2440
23 select CPU_S3C2442
24
25
26endmenu
27
diff --git a/arch/arm/mach-s3c2442/Makefile b/arch/arm/mach-s3c2442/Makefile
new file mode 100644
index 000000000000..2a909c6c5798
--- /dev/null
+++ b/arch/arm/mach-s3c2442/Makefile
@@ -0,0 +1,16 @@
1# arch/arm/mach-s3c2442/Makefile
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7obj-y :=
8obj-m :=
9obj-n :=
10obj- :=
11
12obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
13obj-$(CONFIG_CPU_S3C2442) += clock.o
14
15# Machine support
16
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2442/clock.c
index 4e292ca7c9be..5b9e830ac4d3 100644
--- a/arch/arm/mach-s3c2410/s3c2442-clock.c
+++ b/arch/arm/mach-s3c2442/clock.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c 1/* linux/arch/arm/mach-s3c2442/clock.c
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2004-2005 Simtec Electronics
4 * http://armlinux.simtec.co.uk/ 4 * http://armlinux.simtec.co.uk/
@@ -41,8 +41,8 @@
41 41
42#include <asm/arch/regs-clock.h> 42#include <asm/arch/regs-clock.h>
43 43
44#include "clock.h" 44#include <asm/plat-s3c24xx/clock.h>
45#include "cpu.h" 45#include <asm/plat-s3c24xx/cpu.h>
46 46
47/* S3C2442 extended clock support */ 47/* S3C2442 extended clock support */
48 48
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2442/s3c2442.c
index 428732ee68c4..fbf8264249da 100644
--- a/arch/arm/mach-s3c2410/s3c2442.c
+++ b/arch/arm/mach-s3c2442/s3c2442.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c2442.c 1/* linux/arch/arm/mach-s3c2442/s3c2442.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -19,8 +19,8 @@
19#include <linux/serial_core.h> 19#include <linux/serial_core.h>
20#include <linux/sysdev.h> 20#include <linux/sysdev.h>
21 21
22#include "s3c2442.h" 22#include <asm/plat-s3c24xx/s3c2442.h>
23#include "cpu.h" 23#include <asm/plat-s3c24xx/cpu.h>
24 24
25static struct sys_device s3c2442_sysdev = { 25static struct sys_device s3c2442_sysdev = {
26 .cls = &s3c2442_sysclass, 26 .cls = &s3c2442_sysclass,
diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig
new file mode 100644
index 000000000000..c649bb2e7ce8
--- /dev/null
+++ b/arch/arm/mach-s3c2443/Kconfig
@@ -0,0 +1,29 @@
1# arch/arm/mach-s3c2443/Kconfig
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7config CPU_S3C2443
8 bool
9 depends on ARCH_S3C2410
10 select S3C2443_DMA if S3C2410_DMA
11 help
12 Support for the S3C2443 SoC from the S3C24XX line
13
14config S3C2443_DMA
15 bool
16 depends on CPU_S3C2443
17 help
18 Internal config node for S3C2443 DMA support
19
20menu "S3C2443 Machines"
21
22config MACH_SMDK2443
23 bool "SMDK2443"
24 select CPU_S3C2443
25 select MACH_SMDK
26 help
27 Say Y here if you are using an SMDK2443
28
29endmenu
diff --git a/arch/arm/mach-s3c2443/Makefile b/arch/arm/mach-s3c2443/Makefile
new file mode 100644
index 000000000000..d1843c9eb8bd
--- /dev/null
+++ b/arch/arm/mach-s3c2443/Makefile
@@ -0,0 +1,20 @@
1# arch/arm/mach-s3c2443/Makefile
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7obj-y :=
8obj-m :=
9obj-n :=
10obj- :=
11
12obj-$(CONFIG_CPU_S3C2443) += s3c2443.o
13obj-$(CONFIG_CPU_S3C2443) += irq.o
14obj-$(CONFIG_CPU_S3C2443) += clock.o
15
16obj-$(CONFIG_S3C2443_DMA) += dma.o
17
18# Machine support
19
20obj-$(CONFIG_MACH_SMDK2443) += mach-smdk2443.o
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
new file mode 100644
index 000000000000..dd2272fb1131
--- /dev/null
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -0,0 +1,1007 @@
1/* linux/arch/arm/mach-s3c2443/clock.c
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2443 Clock control support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <linux/init.h>
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/list.h>
27#include <linux/errno.h>
28#include <linux/err.h>
29#include <linux/sysdev.h>
30#include <linux/clk.h>
31#include <linux/mutex.h>
32#include <linux/delay.h>
33#include <linux/serial_core.h>
34
35#include <asm/mach/map.h>
36
37#include <asm/hardware.h>
38#include <asm/io.h>
39
40#include <asm/arch/regs-s3c2443-clock.h>
41
42#include <asm/plat-s3c24xx/s3c2443.h>
43#include <asm/plat-s3c24xx/clock.h>
44#include <asm/plat-s3c24xx/cpu.h>
45
46/* We currently have to assume that the system is running
47 * from the XTPll input, and that all ***REFCLKs are being
48 * fed from it, as we cannot read the state of OM[4] from
49 * software.
50 *
51 * It would be possible for each board initialisation to
52 * set the correct muxing at initialisation
53*/
54
55static int s3c2443_clkcon_enable_h(struct clk *clk, int enable)
56{
57 unsigned int clocks = clk->ctrlbit;
58 unsigned long clkcon;
59
60 clkcon = __raw_readl(S3C2443_HCLKCON);
61
62 if (enable)
63 clkcon |= clocks;
64 else
65 clkcon &= ~clocks;
66
67 __raw_writel(clkcon, S3C2443_HCLKCON);
68
69 return 0;
70}
71
72static int s3c2443_clkcon_enable_p(struct clk *clk, int enable)
73{
74 unsigned int clocks = clk->ctrlbit;
75 unsigned long clkcon;
76
77 clkcon = __raw_readl(S3C2443_PCLKCON);
78
79 if (enable)
80 clkcon |= clocks;
81 else
82 clkcon &= ~clocks;
83
84 __raw_writel(clkcon, S3C2443_HCLKCON);
85
86 return 0;
87}
88
89static int s3c2443_clkcon_enable_s(struct clk *clk, int enable)
90{
91 unsigned int clocks = clk->ctrlbit;
92 unsigned long clkcon;
93
94 clkcon = __raw_readl(S3C2443_SCLKCON);
95
96 if (enable)
97 clkcon |= clocks;
98 else
99 clkcon &= ~clocks;
100
101 __raw_writel(clkcon, S3C2443_SCLKCON);
102
103 return 0;
104}
105
106static unsigned long s3c2443_roundrate_clksrc(struct clk *clk,
107 unsigned long rate,
108 unsigned int max)
109{
110 unsigned long parent_rate = clk_get_rate(clk->parent);
111 int div;
112
113 if (rate > parent_rate)
114 return parent_rate;
115
116 /* note, we remove the +/- 1 calculations as they cancel out */
117
118 div = (rate / parent_rate);
119
120 if (div < 1)
121 div = 1;
122 else if (div > max)
123 div = max;
124
125 return parent_rate / div;
126}
127
128static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk,
129 unsigned long rate)
130{
131 return s3c2443_roundrate_clksrc(clk, rate, 4);
132}
133
134static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk,
135 unsigned long rate)
136{
137 return s3c2443_roundrate_clksrc(clk, rate, 16);
138}
139
140static unsigned long s3c2443_roundrate_clksrc256(struct clk *clk,
141 unsigned long rate)
142{
143 return s3c2443_roundrate_clksrc(clk, rate, 256);
144}
145
146/* clock selections */
147
148/* CPU EXTCLK input */
149static struct clk clk_ext = {
150 .name = "ext",
151 .id = -1,
152};
153
154static struct clk clk_mpllref = {
155 .name = "mpllref",
156 .parent = &clk_xtal,
157 .id = -1,
158};
159
160#if 0
161static struct clk clk_mpll = {
162 .name = "mpll",
163 .parent = &clk_mpllref,
164 .id = -1,
165};
166#endif
167
168static struct clk clk_epllref;
169
170static struct clk clk_epll = {
171 .name = "epll",
172 .parent = &clk_epllref,
173 .id = -1,
174};
175
176static struct clk clk_i2s_ext = {
177 .name = "i2s-ext",
178 .id = -1,
179};
180
181static int s3c2443_setparent_epllref(struct clk *clk, struct clk *parent)
182{
183 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
184
185 clksrc &= ~S3C2443_CLKSRC_EPLLREF_MASK;
186
187 if (parent == &clk_xtal)
188 clksrc |= S3C2443_CLKSRC_EPLLREF_XTAL;
189 else if (parent == &clk_ext)
190 clksrc |= S3C2443_CLKSRC_EPLLREF_EXTCLK;
191 else if (parent != &clk_mpllref)
192 return -EINVAL;
193
194 __raw_writel(clksrc, S3C2443_CLKSRC);
195 clk->parent = parent;
196
197 return 0;
198}
199
200static struct clk clk_epllref = {
201 .name = "epllref",
202 .id = -1,
203 .set_parent = s3c2443_setparent_epllref,
204};
205
206static unsigned long s3c2443_getrate_mdivclk(struct clk *clk)
207{
208 unsigned long parent_rate = clk_get_rate(clk->parent);
209 unsigned long div = __raw_readl(S3C2443_CLKDIV0);
210
211 div &= S3C2443_CLKDIV0_EXTDIV_MASK;
212 div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */
213
214 return parent_rate / (div + 1);
215}
216
217static struct clk clk_mdivclk = {
218 .name = "mdivclk",
219 .parent = &clk_mpllref,
220 .id = -1,
221 .get_rate = s3c2443_getrate_mdivclk,
222};
223
224
225static int s3c2443_setparent_msysclk(struct clk *clk, struct clk *parent)
226{
227 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
228
229 clksrc &= ~(S3C2443_CLKSRC_MSYSCLK_MPLL |
230 S3C2443_CLKSRC_EXTCLK_DIV);
231
232 if (parent == &clk_mpll)
233 clksrc |= S3C2443_CLKSRC_MSYSCLK_MPLL;
234 else if (parent == &clk_mdivclk)
235 clksrc |= S3C2443_CLKSRC_EXTCLK_DIV;
236 else if (parent != &clk_mpllref)
237 return -EINVAL;
238
239 __raw_writel(clksrc, S3C2443_CLKSRC);
240 clk->parent = parent;
241
242 return 0;
243}
244
245static struct clk clk_msysclk = {
246 .name = "msysclk",
247 .parent = &clk_xtal,
248 .id = -1,
249 .set_parent = s3c2443_setparent_msysclk,
250};
251
252
253/* esysclk
254 *
255 * this is sourced from either the EPLL or the EPLLref clock
256*/
257
258static int s3c2443_setparent_esysclk(struct clk *clk, struct clk *parent)
259{
260 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
261
262 if (parent == &clk_epll)
263 clksrc |= S3C2443_CLKSRC_ESYSCLK_EPLL;
264 else if (parent == &clk_epllref)
265 clksrc &= ~S3C2443_CLKSRC_ESYSCLK_EPLL;
266 else
267 return -EINVAL;
268
269 __raw_writel(clksrc, S3C2443_CLKSRC);
270 clk->parent = parent;
271
272 return 0;
273}
274
275static struct clk clk_esysclk = {
276 .name = "esysclk",
277 .parent = &clk_epll,
278 .id = -1,
279 .set_parent = s3c2443_setparent_esysclk,
280};
281
282/* uartclk
283 *
284 * UART baud-rate clock sourced from esysclk via a divisor
285*/
286
287static unsigned long s3c2443_getrate_uart(struct clk *clk)
288{
289 unsigned long parent_rate = clk_get_rate(clk->parent);
290 unsigned long div = __raw_readl(S3C2443_CLKDIV1);
291
292 div &= S3C2443_CLKDIV1_UARTDIV_MASK;
293 div >>= S3C2443_CLKDIV1_UARTDIV_SHIFT;
294
295 return parent_rate / (div + 1);
296}
297
298
299static int s3c2443_setrate_uart(struct clk *clk, unsigned long rate)
300{
301 unsigned long parent_rate = clk_get_rate(clk->parent);
302 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
303
304 rate = s3c2443_roundrate_clksrc16(clk, rate);
305 rate = parent_rate / rate;
306
307 clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
308 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
309
310 __raw_writel(clkdivn, S3C2443_CLKDIV1);
311 return 0;
312}
313
314static struct clk clk_uart = {
315 .name = "uartclk",
316 .id = -1,
317 .parent = &clk_esysclk,
318 .get_rate = s3c2443_getrate_uart,
319 .set_rate = s3c2443_setrate_uart,
320 .round_rate = s3c2443_roundrate_clksrc16,
321};
322
323/* hsspi
324 *
325 * high-speed spi clock, sourced from esysclk
326*/
327
328static unsigned long s3c2443_getrate_hsspi(struct clk *clk)
329{
330 unsigned long parent_rate = clk_get_rate(clk->parent);
331 unsigned long div = __raw_readl(S3C2443_CLKDIV1);
332
333 div &= S3C2443_CLKDIV1_HSSPIDIV_MASK;
334 div >>= S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
335
336 return parent_rate / (div + 1);
337}
338
339
340static int s3c2443_setrate_hsspi(struct clk *clk, unsigned long rate)
341{
342 unsigned long parent_rate = clk_get_rate(clk->parent);
343 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
344
345 rate = s3c2443_roundrate_clksrc4(clk, rate);
346 rate = parent_rate / rate;
347
348 clkdivn &= ~S3C2443_CLKDIV1_HSSPIDIV_MASK;
349 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSSPIDIV_SHIFT;
350
351 __raw_writel(clkdivn, S3C2443_CLKDIV1);
352 return 0;
353}
354
355static struct clk clk_hsspi = {
356 .name = "hsspi",
357 .id = -1,
358 .parent = &clk_esysclk,
359 .ctrlbit = S3C2443_SCLKCON_HSSPICLK,
360 .enable = s3c2443_clkcon_enable_s,
361 .get_rate = s3c2443_getrate_hsspi,
362 .set_rate = s3c2443_setrate_hsspi,
363 .round_rate = s3c2443_roundrate_clksrc4,
364};
365
366/* usbhost
367 *
368 * usb host bus-clock, usually 48MHz to provide USB bus clock timing
369*/
370
371static unsigned long s3c2443_getrate_usbhost(struct clk *clk)
372{
373 unsigned long parent_rate = clk_get_rate(clk->parent);
374 unsigned long div = __raw_readl(S3C2443_CLKDIV1);
375
376 div &= S3C2443_CLKDIV1_USBHOSTDIV_MASK;
377 div >>= S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
378
379 return parent_rate / (div + 1);
380}
381
382static int s3c2443_setrate_usbhost(struct clk *clk, unsigned long rate)
383{
384 unsigned long parent_rate = clk_get_rate(clk->parent);
385 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
386
387 rate = s3c2443_roundrate_clksrc4(clk, rate);
388 rate = parent_rate / rate;
389
390 clkdivn &= ~S3C2443_CLKDIV1_USBHOSTDIV_MASK;
391 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_USBHOSTDIV_SHIFT;
392
393 __raw_writel(clkdivn, S3C2443_CLKDIV1);
394 return 0;
395}
396
397struct clk clk_usb_bus_host = {
398 .name = "usb-bus-host-parent",
399 .id = -1,
400 .parent = &clk_esysclk,
401 .ctrlbit = S3C2443_SCLKCON_USBHOST,
402 .enable = s3c2443_clkcon_enable_s,
403 .get_rate = s3c2443_getrate_usbhost,
404 .set_rate = s3c2443_setrate_usbhost,
405 .round_rate = s3c2443_roundrate_clksrc4,
406};
407
408/* clk_hsmcc_div
409 *
410 * this clock is sourced from epll, and is fed through a divider,
411 * to a mux controlled by sclkcon where either it or a extclk can
412 * be fed to the hsmmc block
413*/
414
415static unsigned long s3c2443_getrate_hsmmc_div(struct clk *clk)
416{
417 unsigned long parent_rate = clk_get_rate(clk->parent);
418 unsigned long div = __raw_readl(S3C2443_CLKDIV1);
419
420 div &= S3C2443_CLKDIV1_HSMMCDIV_MASK;
421 div >>= S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
422
423 return parent_rate / (div + 1);
424}
425
426static int s3c2443_setrate_hsmmc_div(struct clk *clk, unsigned long rate)
427{
428 unsigned long parent_rate = clk_get_rate(clk->parent);
429 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
430
431 rate = s3c2443_roundrate_clksrc4(clk, rate);
432 rate = parent_rate / rate;
433
434 clkdivn &= ~S3C2443_CLKDIV1_HSMMCDIV_MASK;
435 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_HSMMCDIV_SHIFT;
436
437 __raw_writel(clkdivn, S3C2443_CLKDIV1);
438 return 0;
439}
440
441static struct clk clk_hsmmc_div = {
442 .name = "hsmmc-div",
443 .id = -1,
444 .parent = &clk_esysclk,
445 .get_rate = s3c2443_getrate_hsmmc_div,
446 .set_rate = s3c2443_setrate_hsmmc_div,
447 .round_rate = s3c2443_roundrate_clksrc4,
448};
449
450static int s3c2443_setparent_hsmmc(struct clk *clk, struct clk *parent)
451{
452 unsigned long clksrc = __raw_readl(S3C2443_SCLKCON);
453
454 clksrc &= ~(S3C2443_SCLKCON_HSMMCCLK_EXT |
455 S3C2443_SCLKCON_HSMMCCLK_EPLL);
456
457 if (parent == &clk_epll)
458 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EPLL;
459 else if (parent == &clk_ext)
460 clksrc |= S3C2443_SCLKCON_HSMMCCLK_EXT;
461 else
462 return -EINVAL;
463
464 if (clk->usage > 0) {
465 __raw_writel(clksrc, S3C2443_SCLKCON);
466 }
467
468 clk->parent = parent;
469 return 0;
470}
471
472static int s3c2443_enable_hsmmc(struct clk *clk, int enable)
473{
474 return s3c2443_setparent_hsmmc(clk, clk->parent);
475}
476
477static struct clk clk_hsmmc = {
478 .name = "hsmmc-if",
479 .id = -1,
480 .parent = &clk_hsmmc_div,
481 .enable = s3c2443_enable_hsmmc,
482 .set_parent = s3c2443_setparent_hsmmc,
483};
484
485/* i2s_eplldiv
486 *
487 * this clock is the output from the i2s divisor of esysclk
488*/
489
490static unsigned long s3c2443_getrate_i2s_eplldiv(struct clk *clk)
491{
492 unsigned long parent_rate = clk_get_rate(clk->parent);
493 unsigned long div = __raw_readl(S3C2443_CLKDIV1);
494
495 div &= S3C2443_CLKDIV1_I2SDIV_MASK;
496 div >>= S3C2443_CLKDIV1_I2SDIV_SHIFT;
497
498 return parent_rate / (div + 1);
499}
500
501static int s3c2443_setrate_i2s_eplldiv(struct clk *clk, unsigned long rate)
502{
503 unsigned long parent_rate = clk_get_rate(clk->parent);
504 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
505
506 rate = s3c2443_roundrate_clksrc16(clk, rate);
507 rate = parent_rate / rate;
508
509 clkdivn &= ~S3C2443_CLKDIV1_I2SDIV_MASK;
510 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_I2SDIV_SHIFT;
511
512 __raw_writel(clkdivn, S3C2443_CLKDIV1);
513 return 0;
514}
515
516static struct clk clk_i2s_eplldiv = {
517 .name = "i2s-eplldiv",
518 .id = -1,
519 .parent = &clk_esysclk,
520 .get_rate = s3c2443_getrate_i2s_eplldiv,
521 .set_rate = s3c2443_setrate_i2s_eplldiv,
522 .round_rate = s3c2443_roundrate_clksrc16,
523};
524
525/* i2s-ref
526 *
527 * i2s bus reference clock, selectable from external, esysclk or epllref
528*/
529
530static int s3c2443_setparent_i2s(struct clk *clk, struct clk *parent)
531{
532 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
533
534 clksrc &= ~S3C2443_CLKSRC_I2S_MASK;
535
536 if (parent == &clk_epllref)
537 clksrc |= S3C2443_CLKSRC_I2S_EPLLREF;
538 else if (parent == &clk_i2s_ext)
539 clksrc |= S3C2443_CLKSRC_I2S_EXT;
540 else if (parent != &clk_i2s_eplldiv)
541 return -EINVAL;
542
543 clk->parent = parent;
544 __raw_writel(clksrc, S3C2443_CLKSRC);
545
546 return 0;
547}
548
549static struct clk clk_i2s = {
550 .name = "i2s-if",
551 .id = -1,
552 .parent = &clk_i2s_eplldiv,
553 .ctrlbit = S3C2443_SCLKCON_I2SCLK,
554 .enable = s3c2443_clkcon_enable_s,
555 .set_parent = s3c2443_setparent_i2s,
556};
557
558/* cam-if
559 *
560 * camera interface bus-clock, divided down from esysclk
561*/
562
563static unsigned long s3c2443_getrate_cam(struct clk *clk)
564{
565 unsigned long parent_rate = clk_get_rate(clk->parent);
566 unsigned long div = __raw_readl(S3C2443_CLKDIV1);
567
568 div &= S3C2443_CLKDIV1_CAMDIV_MASK;
569 div >>= S3C2443_CLKDIV1_CAMDIV_SHIFT;
570
571 return parent_rate / (div + 1);
572}
573
574static int s3c2443_setrate_cam(struct clk *clk, unsigned long rate)
575{
576 unsigned long parent_rate = clk_get_rate(clk->parent);
577 unsigned long clkdiv1 = __raw_readl(S3C2443_CLKDIV1);
578
579 rate = s3c2443_roundrate_clksrc16(clk, rate);
580 rate = parent_rate / rate;
581
582 clkdiv1 &= ~S3C2443_CLKDIV1_CAMDIV_MASK;
583 clkdiv1 |= (rate - 1) << S3C2443_CLKDIV1_CAMDIV_SHIFT;
584
585 __raw_writel(clkdiv1, S3C2443_CLKDIV1);
586 return 0;
587}
588
589static struct clk clk_cam = {
590 .name = "camif-upll", /* same as 2440 name */
591 .id = -1,
592 .parent = &clk_esysclk,
593 .ctrlbit = S3C2443_SCLKCON_CAMCLK,
594 .enable = s3c2443_clkcon_enable_s,
595 .get_rate = s3c2443_getrate_cam,
596 .set_rate = s3c2443_setrate_cam,
597 .round_rate = s3c2443_roundrate_clksrc16,
598};
599
600/* display-if
601 *
602 * display interface clock, divided from esysclk
603*/
604
605static unsigned long s3c2443_getrate_display(struct clk *clk)
606{
607 unsigned long parent_rate = clk_get_rate(clk->parent);
608 unsigned long div = __raw_readl(S3C2443_CLKDIV1);
609
610 div &= S3C2443_CLKDIV1_DISPDIV_MASK;
611 div >>= S3C2443_CLKDIV1_DISPDIV_SHIFT;
612
613 return parent_rate / (div + 1);
614}
615
616static int s3c2443_setrate_display(struct clk *clk, unsigned long rate)
617{
618 unsigned long parent_rate = clk_get_rate(clk->parent);
619 unsigned long clkdivn = __raw_readl(S3C2443_CLKDIV1);
620
621 rate = s3c2443_roundrate_clksrc256(clk, rate);
622 rate = parent_rate / rate;
623
624 clkdivn &= ~S3C2443_CLKDIV1_UARTDIV_MASK;
625 clkdivn |= (rate - 1) << S3C2443_CLKDIV1_UARTDIV_SHIFT;
626
627 __raw_writel(clkdivn, S3C2443_CLKDIV1);
628 return 0;
629}
630
631static struct clk clk_display = {
632 .name = "display-if",
633 .id = -1,
634 .parent = &clk_esysclk,
635 .ctrlbit = S3C2443_SCLKCON_DISPCLK,
636 .enable = s3c2443_clkcon_enable_s,
637 .get_rate = s3c2443_getrate_display,
638 .set_rate = s3c2443_setrate_display,
639 .round_rate = s3c2443_roundrate_clksrc256,
640};
641
642/* standard clock definitions */
643
644static struct clk init_clocks_disable[] = {
645 {
646 .name = "nand",
647 .id = -1,
648 .parent = &clk_h,
649 }, {
650 .name = "sdi",
651 .id = -1,
652 .parent = &clk_p,
653 .enable = s3c2443_clkcon_enable_p,
654 .ctrlbit = S3C2443_PCLKCON_SDI,
655 }, {
656 .name = "adc",
657 .id = -1,
658 .parent = &clk_p,
659 .enable = s3c2443_clkcon_enable_p,
660 .ctrlbit = S3C2443_PCLKCON_ADC,
661 }, {
662 .name = "i2c",
663 .id = -1,
664 .parent = &clk_p,
665 .enable = s3c2443_clkcon_enable_p,
666 .ctrlbit = S3C2443_PCLKCON_IIC,
667 }, {
668 .name = "iis",
669 .id = -1,
670 .parent = &clk_p,
671 .enable = s3c2443_clkcon_enable_p,
672 .ctrlbit = S3C2443_PCLKCON_IIS,
673 }, {
674 .name = "spi",
675 .id = 0,
676 .parent = &clk_p,
677 .enable = s3c2443_clkcon_enable_p,
678 .ctrlbit = S3C2443_PCLKCON_SPI0,
679 }, {
680 .name = "spi",
681 .id = 1,
682 .parent = &clk_p,
683 .enable = s3c2443_clkcon_enable_p,
684 .ctrlbit = S3C2443_PCLKCON_SPI1,
685 }
686};
687
688static struct clk init_clocks[] = {
689 {
690 .name = "dma",
691 .id = 0,
692 .parent = &clk_h,
693 .enable = s3c2443_clkcon_enable_h,
694 .ctrlbit = S3C2443_HCLKCON_DMA0,
695 }, {
696 .name = "dma",
697 .id = 1,
698 .parent = &clk_h,
699 .enable = s3c2443_clkcon_enable_h,
700 .ctrlbit = S3C2443_HCLKCON_DMA1,
701 }, {
702 .name = "dma",
703 .id = 2,
704 .parent = &clk_h,
705 .enable = s3c2443_clkcon_enable_h,
706 .ctrlbit = S3C2443_HCLKCON_DMA2,
707 }, {
708 .name = "dma",
709 .id = 3,
710 .parent = &clk_h,
711 .enable = s3c2443_clkcon_enable_h,
712 .ctrlbit = S3C2443_HCLKCON_DMA3,
713 }, {
714 .name = "dma",
715 .id = 4,
716 .parent = &clk_h,
717 .enable = s3c2443_clkcon_enable_h,
718 .ctrlbit = S3C2443_HCLKCON_DMA4,
719 }, {
720 .name = "dma",
721 .id = 5,
722 .parent = &clk_h,
723 .enable = s3c2443_clkcon_enable_h,
724 .ctrlbit = S3C2443_HCLKCON_DMA5,
725 }, {
726 .name = "lcd",
727 .id = -1,
728 .parent = &clk_h,
729 .enable = s3c2443_clkcon_enable_h,
730 .ctrlbit = S3C2443_HCLKCON_LCDC,
731 }, {
732 .name = "gpio",
733 .id = -1,
734 .parent = &clk_p,
735 .enable = s3c2443_clkcon_enable_p,
736 .ctrlbit = S3C2443_PCLKCON_GPIO,
737 }, {
738 .name = "usb-host",
739 .id = -1,
740 .parent = &clk_h,
741 .enable = s3c2443_clkcon_enable_h,
742 .ctrlbit = S3C2443_HCLKCON_USBH,
743 }, {
744 .name = "usb-device",
745 .id = -1,
746 .parent = &clk_h,
747 .enable = s3c2443_clkcon_enable_h,
748 .ctrlbit = S3C2443_HCLKCON_USBD,
749 }, {
750 .name = "timers",
751 .id = -1,
752 .parent = &clk_p,
753 .enable = s3c2443_clkcon_enable_p,
754 .ctrlbit = S3C2443_PCLKCON_PWMT,
755 }, {
756 .name = "uart",
757 .id = 0,
758 .parent = &clk_p,
759 .enable = s3c2443_clkcon_enable_p,
760 .ctrlbit = S3C2443_PCLKCON_UART0,
761 }, {
762 .name = "uart",
763 .id = 1,
764 .parent = &clk_p,
765 .enable = s3c2443_clkcon_enable_p,
766 .ctrlbit = S3C2443_PCLKCON_UART1,
767 }, {
768 .name = "uart",
769 .id = 2,
770 .parent = &clk_p,
771 .enable = s3c2443_clkcon_enable_p,
772 .ctrlbit = S3C2443_PCLKCON_UART2,
773 }, {
774 .name = "uart",
775 .id = 3,
776 .parent = &clk_p,
777 .enable = s3c2443_clkcon_enable_p,
778 .ctrlbit = S3C2443_PCLKCON_UART3,
779 }, {
780 .name = "rtc",
781 .id = -1,
782 .parent = &clk_p,
783 .enable = s3c2443_clkcon_enable_p,
784 .ctrlbit = S3C2443_PCLKCON_RTC,
785 }, {
786 .name = "watchdog",
787 .id = -1,
788 .parent = &clk_p,
789 .ctrlbit = S3C2443_PCLKCON_WDT,
790 }, {
791 .name = "usb-bus-host",
792 .id = -1,
793 .parent = &clk_usb_bus_host,
794 }
795};
796
797/* clocks to add where we need to check their parentage */
798
799/* s3c2443_clk_initparents
800 *
801 * Initialise the parents for the clocks that we get at start-time
802*/
803
804static int __init clk_init_set_parent(struct clk *clk, struct clk *parent)
805{
806 printk(KERN_DEBUG "clock %s: parent %s\n", clk->name, parent->name);
807 return clk_set_parent(clk, parent);
808}
809
810static void __init s3c2443_clk_initparents(void)
811{
812 unsigned long clksrc = __raw_readl(S3C2443_CLKSRC);
813 struct clk *parent;
814
815 switch (clksrc & S3C2443_CLKSRC_EPLLREF_MASK) {
816 case S3C2443_CLKSRC_EPLLREF_EXTCLK:
817 parent = &clk_ext;
818 break;
819
820 case S3C2443_CLKSRC_EPLLREF_XTAL:
821 default:
822 parent = &clk_xtal;
823 break;
824
825 case S3C2443_CLKSRC_EPLLREF_MPLLREF:
826 case S3C2443_CLKSRC_EPLLREF_MPLLREF2:
827 parent = &clk_mpllref;
828 break;
829 }
830
831 clk_init_set_parent(&clk_epllref, parent);
832
833 switch (clksrc & S3C2443_CLKSRC_I2S_MASK) {
834 case S3C2443_CLKSRC_I2S_EXT:
835 parent = &clk_i2s_ext;
836 break;
837
838 case S3C2443_CLKSRC_I2S_EPLLDIV:
839 default:
840 parent = &clk_i2s_eplldiv;
841 break;
842
843 case S3C2443_CLKSRC_I2S_EPLLREF:
844 case S3C2443_CLKSRC_I2S_EPLLREF3:
845 parent = &clk_epllref;
846 }
847
848 clk_init_set_parent(&clk_i2s, &clk_epllref);
849
850 /* esysclk source */
851
852 parent = (clksrc & S3C2443_CLKSRC_ESYSCLK_EPLL) ?
853 &clk_epll : &clk_epllref;
854
855 clk_init_set_parent(&clk_esysclk, parent);
856
857 /* msysclk source */
858
859 if (clksrc & S3C2443_CLKSRC_MSYSCLK_MPLL) {
860 parent = &clk_mpll;
861 } else {
862 parent = (clksrc & S3C2443_CLKSRC_EXTCLK_DIV) ?
863 &clk_mdivclk : &clk_mpllref;
864 }
865
866 clk_init_set_parent(&clk_msysclk, parent);
867}
868
869/* armdiv divisor table */
870
871static unsigned int armdiv[16] = {
872 [S3C2443_CLKDIV0_ARMDIV_1 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 1,
873 [S3C2443_CLKDIV0_ARMDIV_2 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 2,
874 [S3C2443_CLKDIV0_ARMDIV_3 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 3,
875 [S3C2443_CLKDIV0_ARMDIV_4 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 4,
876 [S3C2443_CLKDIV0_ARMDIV_6 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 6,
877 [S3C2443_CLKDIV0_ARMDIV_8 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 8,
878 [S3C2443_CLKDIV0_ARMDIV_12 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 12,
879 [S3C2443_CLKDIV0_ARMDIV_16 >> S3C2443_CLKDIV0_ARMDIV_SHIFT] = 16,
880};
881
882static inline unsigned int s3c2443_fclk_div(unsigned long clkcon0)
883{
884 clkcon0 &= S3C2443_CLKDIV0_ARMDIV_MASK;
885
886 return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT];
887}
888
889static inline unsigned long s3c2443_get_prediv(unsigned long clkcon0)
890{
891 clkcon0 &= S3C2443_CLKDIV0_PREDIV_MASK;
892 clkcon0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT;
893
894 return clkcon0 + 1;
895}
896
897/* clocks to add straight away */
898
899static struct clk *clks[] __initdata = {
900 &clk_ext,
901 &clk_epll,
902 &clk_usb_bus_host,
903 &clk_usb_bus,
904 &clk_esysclk,
905 &clk_epllref,
906 &clk_mpllref,
907 &clk_msysclk,
908 &clk_uart,
909 &clk_display,
910 &clk_cam,
911 &clk_i2s_eplldiv,
912 &clk_i2s,
913 &clk_hsspi,
914 &clk_hsmmc_div,
915 &clk_hsmmc,
916};
917
918void __init s3c2443_init_clocks(int xtal)
919{
920 unsigned long epllcon = __raw_readl(S3C2443_EPLLCON);
921 unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON);
922 unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0);
923 unsigned long pll;
924 unsigned long fclk;
925 unsigned long hclk;
926 unsigned long pclk;
927 struct clk *clkp;
928 int ret;
929 int ptr;
930
931 pll = s3c2443_get_mpll(mpllcon, xtal);
932
933 fclk = pll / s3c2443_fclk_div(clkdiv0);
934 hclk = fclk / s3c2443_get_prediv(clkdiv0);
935 hclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_HCLK) ? 2 : 1);
936 pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1);
937
938 s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
939
940 printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n",
941 (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on",
942 print_mhz(pll), print_mhz(fclk),
943 print_mhz(hclk), print_mhz(pclk));
944
945 s3c2443_clk_initparents();
946
947 for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
948 clkp = clks[ptr];
949
950 ret = s3c24xx_register_clock(clkp);
951 if (ret < 0) {
952 printk(KERN_ERR "Failed to register clock %s (%d)\n",
953 clkp->name, ret);
954 }
955 }
956
957 clk_epll.rate = s3c2443_get_epll(epllcon, xtal);
958
959 clk_usb_bus.parent = &clk_usb_bus_host;
960
961 /* ensure usb bus clock is within correct rate of 48MHz */
962
963 if (clk_get_rate(&clk_usb_bus_host) != (48 * 1000 * 1000)) {
964 printk(KERN_INFO "Warning: USB host bus not at 48MHz\n");
965 clk_set_rate(&clk_usb_bus_host, 48*1000*1000);
966 }
967
968 printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
969 (epllcon & S3C2443_PLLCON_OFF) ? "off":"on",
970 print_mhz(clk_get_rate(&clk_epll)),
971 print_mhz(clk_get_rate(&clk_usb_bus)));
972
973 /* register clocks from clock array */
974
975 clkp = init_clocks;
976 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
977 ret = s3c24xx_register_clock(clkp);
978 if (ret < 0) {
979 printk(KERN_ERR "Failed to register clock %s (%d)\n",
980 clkp->name, ret);
981 }
982 }
983
984 /* We must be careful disabling the clocks we are not intending to
985 * be using at boot time, as subsytems such as the LCD which do
986 * their own DMA requests to the bus can cause the system to lockup
987 * if they where in the middle of requesting bus access.
988 *
989 * Disabling the LCD clock if the LCD is active is very dangerous,
990 * and therefore the bootloader should be careful to not enable
991 * the LCD clock if it is not needed.
992 */
993
994 /* install (and disable) the clocks we do not need immediately */
995
996 clkp = init_clocks_disable;
997 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
998
999 ret = s3c24xx_register_clock(clkp);
1000 if (ret < 0) {
1001 printk(KERN_ERR "Failed to register clock %s (%d)\n",
1002 clkp->name, ret);
1003 }
1004
1005 (clkp->enable)(clkp, 0);
1006 }
1007}
diff --git a/arch/arm/mach-s3c2443/dma.c b/arch/arm/mach-s3c2443/dma.c
new file mode 100644
index 000000000000..f70e8ccffc3d
--- /dev/null
+++ b/arch/arm/mach-s3c2443/dma.c
@@ -0,0 +1,180 @@
1/* linux/arch/arm/mach-s3c2443/dma.c
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2443 DMA selection
7 *
8 * http://armlinux.simtec.co.uk/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/sysdev.h>
18#include <linux/serial_core.h>
19
20#include <asm/dma.h>
21#include <asm/arch/dma.h>
22#include <asm/io.h>
23
24#include <asm/plat-s3c24xx/dma.h>
25#include <asm/plat-s3c24xx/cpu.h>
26
27#include <asm/arch/regs-serial.h>
28#include <asm/arch/regs-gpio.h>
29#include <asm/arch/regs-ac97.h>
30#include <asm/arch/regs-mem.h>
31#include <asm/arch/regs-lcd.h>
32#include <asm/arch/regs-sdi.h>
33#include <asm/arch/regs-iis.h>
34#include <asm/arch/regs-spi.h>
35
36#define MAP(x) { \
37 [0] = (x) | DMA_CH_VALID, \
38 [1] = (x) | DMA_CH_VALID, \
39 [2] = (x) | DMA_CH_VALID, \
40 [3] = (x) | DMA_CH_VALID, \
41 [4] = (x) | DMA_CH_VALID, \
42 [5] = (x) | DMA_CH_VALID, \
43 }
44
45static struct s3c24xx_dma_map __initdata s3c2443_dma_mappings[] = {
46 [DMACH_XD0] = {
47 .name = "xdreq0",
48 .channels = MAP(S3C2443_DMAREQSEL_XDREQ0),
49 },
50 [DMACH_XD1] = {
51 .name = "xdreq1",
52 .channels = MAP(S3C2443_DMAREQSEL_XDREQ1),
53 },
54 [DMACH_SDI] = {
55 .name = "sdi",
56 .channels = MAP(S3C2443_DMAREQSEL_SDI),
57 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
58 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
59 },
60 [DMACH_SPI0] = {
61 .name = "spi0",
62 .channels = MAP(S3C2443_DMAREQSEL_SPI0TX),
63 .hw_addr.to = S3C2410_PA_SPI + S3C2410_SPTDAT,
64 .hw_addr.from = S3C2410_PA_SPI + S3C2410_SPRDAT,
65 },
66 [DMACH_SPI1] = {
67 .name = "spi1",
68 .channels = MAP(S3C2443_DMAREQSEL_SPI1TX),
69 .hw_addr.to = S3C2410_PA_SPI + 0x20 + S3C2410_SPTDAT,
70 .hw_addr.from = S3C2410_PA_SPI + 0x20 + S3C2410_SPRDAT,
71 },
72 [DMACH_UART0] = {
73 .name = "uart0",
74 .channels = MAP(S3C2443_DMAREQSEL_UART0_0),
75 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
76 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
77 },
78 [DMACH_UART1] = {
79 .name = "uart1",
80 .channels = MAP(S3C2443_DMAREQSEL_UART1_0),
81 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
82 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
83 },
84 [DMACH_UART2] = {
85 .name = "uart2",
86 .channels = MAP(S3C2443_DMAREQSEL_UART2_0),
87 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
88 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
89 },
90 [DMACH_UART3] = {
91 .name = "uart3",
92 .channels = MAP(S3C2443_DMAREQSEL_UART3_0),
93 .hw_addr.to = S3C2443_PA_UART3 + S3C2410_UTXH,
94 .hw_addr.from = S3C2443_PA_UART3 + S3C2410_URXH,
95 },
96 [DMACH_UART0_SRC2] = {
97 .name = "uart0",
98 .channels = MAP(S3C2443_DMAREQSEL_UART0_1),
99 .hw_addr.to = S3C2410_PA_UART0 + S3C2410_UTXH,
100 .hw_addr.from = S3C2410_PA_UART0 + S3C2410_URXH,
101 },
102 [DMACH_UART1_SRC2] = {
103 .name = "uart1",
104 .channels = MAP(S3C2443_DMAREQSEL_UART1_1),
105 .hw_addr.to = S3C2410_PA_UART1 + S3C2410_UTXH,
106 .hw_addr.from = S3C2410_PA_UART1 + S3C2410_URXH,
107 },
108 [DMACH_UART2_SRC2] = {
109 .name = "uart2",
110 .channels = MAP(S3C2443_DMAREQSEL_UART2_1),
111 .hw_addr.to = S3C2410_PA_UART2 + S3C2410_UTXH,
112 .hw_addr.from = S3C2410_PA_UART2 + S3C2410_URXH,
113 },
114 [DMACH_UART3_SRC2] = {
115 .name = "uart3",
116 .channels = MAP(S3C2443_DMAREQSEL_UART3_1),
117 .hw_addr.to = S3C2443_PA_UART3 + S3C2410_UTXH,
118 .hw_addr.from = S3C2443_PA_UART3 + S3C2410_URXH,
119 },
120 [DMACH_TIMER] = {
121 .name = "timer",
122 .channels = MAP(S3C2443_DMAREQSEL_TIMER),
123 },
124 [DMACH_I2S_IN] = {
125 .name = "i2s-sdi",
126 .channels = MAP(S3C2443_DMAREQSEL_I2SRX),
127 .hw_addr.from = S3C2410_PA_IIS + S3C2410_IISFIFO,
128 },
129 [DMACH_I2S_OUT] = {
130 .name = "i2s-sdo",
131 .channels = MAP(S3C2443_DMAREQSEL_I2STX),
132 .hw_addr.to = S3C2410_PA_IIS + S3C2410_IISFIFO,
133 },
134 [DMACH_PCM_IN] = {
135 .name = "pcm-in",
136 .channels = MAP(S3C2443_DMAREQSEL_PCMIN),
137 .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
138 },
139 [DMACH_PCM_OUT] = {
140 .name = "pcm-out",
141 .channels = MAP(S3C2443_DMAREQSEL_PCMOUT),
142 .hw_addr.to = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
143 },
144 [DMACH_MIC_IN] = {
145 .name = "mic-in",
146 .channels = MAP(S3C2443_DMAREQSEL_MICIN),
147 .hw_addr.from = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
148 },
149};
150
151static void s3c2443_dma_select(struct s3c2410_dma_chan *chan,
152 struct s3c24xx_dma_map *map)
153{
154 writel(map->channels[0] | S3C2443_DMAREQSEL_HW,
155 chan->regs + S3C2443_DMA_DMAREQSEL);
156}
157
158static struct s3c24xx_dma_selection __initdata s3c2443_dma_sel = {
159 .select = s3c2443_dma_select,
160 .dcon_mask = 0,
161 .map = s3c2443_dma_mappings,
162 .map_size = ARRAY_SIZE(s3c2443_dma_mappings),
163};
164
165static int s3c2443_dma_add(struct sys_device *sysdev)
166{
167 s3c24xx_dma_init(6, IRQ_S3C2443_DMA0, 0x100);
168 return s3c24xx_dma_init_map(&s3c2443_dma_sel);
169}
170
171static struct sysdev_driver s3c2443_dma_driver = {
172 .add = s3c2443_dma_add,
173};
174
175static int __init s3c2443_dma_init(void)
176{
177 return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_dma_driver);
178}
179
180arch_initcall(s3c2443_dma_init);
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c
new file mode 100644
index 000000000000..7a45b6dcb73e
--- /dev/null
+++ b/arch/arm/mach-s3c2443/irq.c
@@ -0,0 +1,290 @@
1/* linux/arch/arm/mach-s3c2443/irq.c
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20*/
21
22#include <linux/init.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/ioport.h>
26#include <linux/ptrace.h>
27#include <linux/sysdev.h>
28
29#include <asm/hardware.h>
30#include <asm/irq.h>
31#include <asm/io.h>
32
33#include <asm/mach/irq.h>
34
35#include <asm/arch/regs-irq.h>
36#include <asm/arch/regs-gpio.h>
37
38#include <asm/plat-s3c24xx/cpu.h>
39#include <asm/plat-s3c24xx/pm.h>
40#include <asm/plat-s3c24xx/irq.h>
41
42#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
43
44static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len)
45{
46 unsigned int subsrc, submsk;
47 unsigned int end;
48 struct irq_desc *mydesc;
49
50 /* read the current pending interrupts, and the mask
51 * for what it is available */
52
53 subsrc = __raw_readl(S3C2410_SUBSRCPND);
54 submsk = __raw_readl(S3C2410_INTSUBMSK);
55
56 subsrc &= ~submsk;
57 subsrc >>= (irq - S3C2410_IRQSUB(0));
58 subsrc &= (1 << len)-1;
59
60 end = len + irq;
61 mydesc = irq_desc + irq;
62
63 for (; irq < end && subsrc; irq++) {
64 if (subsrc & 1)
65 desc_handle_irq(irq, mydesc);
66
67 mydesc++;
68 subsrc >>= 1;
69 }
70}
71
72/* WDT/AC97 sub interrupts */
73
74static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc)
75{
76 s3c2443_irq_demux(IRQ_S3C2443_WDT, 4);
77}
78
79#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0))
80#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97)
81
82static void s3c2443_irq_wdtac97_mask(unsigned int irqno)
83{
84 s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
85}
86
87static void s3c2443_irq_wdtac97_unmask(unsigned int irqno)
88{
89 s3c_irqsub_unmask(irqno, INTMSK_WDTAC97);
90}
91
92static void s3c2443_irq_wdtac97_ack(unsigned int irqno)
93{
94 s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97);
95}
96
97static struct irq_chip s3c2443_irq_wdtac97 = {
98 .mask = s3c2443_irq_wdtac97_mask,
99 .unmask = s3c2443_irq_wdtac97_unmask,
100 .ack = s3c2443_irq_wdtac97_ack,
101};
102
103
104/* LCD sub interrupts */
105
106static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc)
107{
108 s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4);
109}
110
111#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
112#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4)
113
114static void s3c2443_irq_lcd_mask(unsigned int irqno)
115{
116 s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD);
117}
118
119static void s3c2443_irq_lcd_unmask(unsigned int irqno)
120{
121 s3c_irqsub_unmask(irqno, INTMSK_LCD);
122}
123
124static void s3c2443_irq_lcd_ack(unsigned int irqno)
125{
126 s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD);
127}
128
129static struct irq_chip s3c2443_irq_lcd = {
130 .mask = s3c2443_irq_lcd_mask,
131 .unmask = s3c2443_irq_lcd_unmask,
132 .ack = s3c2443_irq_lcd_ack,
133};
134
135
136/* DMA sub interrupts */
137
138static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc)
139{
140 s3c2443_irq_demux(IRQ_S3C2443_DMA1, 6);
141}
142
143#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0))
144#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5)
145
146
147static void s3c2443_irq_dma_mask(unsigned int irqno)
148{
149 s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA);
150}
151
152static void s3c2443_irq_dma_unmask(unsigned int irqno)
153{
154 s3c_irqsub_unmask(irqno, INTMSK_DMA);
155}
156
157static void s3c2443_irq_dma_ack(unsigned int irqno)
158{
159 s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA);
160}
161
162static struct irq_chip s3c2443_irq_dma = {
163 .mask = s3c2443_irq_dma_mask,
164 .unmask = s3c2443_irq_dma_unmask,
165 .ack = s3c2443_irq_dma_ack,
166};
167
168
169/* UART3 sub interrupts */
170
171static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
172{
173 s3c2443_irq_demux(IRQ_S3C2443_UART3, 3);
174}
175
176#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
177#define SUBMSK_UART3 (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
178
179
180static void s3c2443_irq_uart3_mask(unsigned int irqno)
181{
182 s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3);
183}
184
185static void s3c2443_irq_uart3_unmask(unsigned int irqno)
186{
187 s3c_irqsub_unmask(irqno, INTMSK_UART3);
188}
189
190static void s3c2443_irq_uart3_ack(unsigned int irqno)
191{
192 s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3);
193}
194
195static struct irq_chip s3c2443_irq_uart3 = {
196 .mask = s3c2443_irq_uart3_mask,
197 .unmask = s3c2443_irq_uart3_unmask,
198 .ack = s3c2443_irq_uart3_ack,
199};
200
201
202/* CAM sub interrupts */
203
204static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc)
205{
206 s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4);
207}
208
209#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
210#define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P)
211
212static void s3c2443_irq_cam_mask(unsigned int irqno)
213{
214 s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM);
215}
216
217static void s3c2443_irq_cam_unmask(unsigned int irqno)
218{
219 s3c_irqsub_unmask(irqno, INTMSK_CAM);
220}
221
222static void s3c2443_irq_cam_ack(unsigned int irqno)
223{
224 s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM);
225}
226
227static struct irq_chip s3c2443_irq_cam = {
228 .mask = s3c2443_irq_cam_mask,
229 .unmask = s3c2443_irq_cam_unmask,
230 .ack = s3c2443_irq_cam_ack,
231};
232
233/* IRQ initialisation code */
234
235static int __init s3c2443_add_sub(unsigned int base,
236 void (*demux)(unsigned int,
237 struct irq_desc *),
238 struct irq_chip *chip,
239 unsigned int start, unsigned int end)
240{
241 unsigned int irqno;
242
243 set_irq_chip(base, &s3c_irq_level_chip);
244 set_irq_handler(base, handle_level_irq);
245 set_irq_chained_handler(base, demux);
246
247 for (irqno = start; irqno <= end; irqno++) {
248 set_irq_chip(irqno, chip);
249 set_irq_handler(irqno, handle_level_irq);
250 set_irq_flags(irqno, IRQF_VALID);
251 }
252
253 return 0;
254}
255
256static int s3c2443_irq_add(struct sys_device *sysdev)
257{
258 printk("S3C2443: IRQ Support\n");
259
260 s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam,
261 IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P);
262
263 s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd,
264 IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4);
265
266 s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma,
267 &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5);
268
269 s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3,
270 &s3c2443_irq_uart3,
271 IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3);
272
273 s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97,
274 &s3c2443_irq_wdtac97,
275 IRQ_S3C2443_WDT, IRQ_S3C2443_AC97);
276
277 return 0;
278}
279
280static struct sysdev_driver s3c2443_irq_driver = {
281 .add = s3c2443_irq_add,
282};
283
284static int s3c2443_irq_init(void)
285{
286 return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_irq_driver);
287}
288
289arch_initcall(s3c2443_irq_init);
290
diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c
new file mode 100644
index 000000000000..e82aaff7dee4
--- /dev/null
+++ b/arch/arm/mach-s3c2443/mach-smdk2443.c
@@ -0,0 +1,137 @@
1/* linux/arch/arm/mach-s3c2443/mach-smdk2443.c
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * http://www.fluff.org/ben/smdk2443/
7 *
8 * Thanks to Samsung for the loan of an SMDK2443
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14*/
15
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/interrupt.h>
19#include <linux/list.h>
20#include <linux/timer.h>
21#include <linux/init.h>
22#include <linux/serial_core.h>
23#include <linux/platform_device.h>
24
25#include <asm/mach/arch.h>
26#include <asm/mach/map.h>
27#include <asm/mach/irq.h>
28
29#include <asm/hardware.h>
30#include <asm/io.h>
31#include <asm/irq.h>
32#include <asm/mach-types.h>
33
34#include <asm/arch/regs-serial.h>
35#include <asm/arch/regs-gpio.h>
36#include <asm/arch/regs-lcd.h>
37
38#include <asm/arch/idle.h>
39#include <asm/arch/fb.h>
40
41#include <asm/plat-s3c24xx/s3c2410.h>
42#include <asm/plat-s3c24xx/s3c2440.h>
43#include <asm/plat-s3c24xx/clock.h>
44#include <asm/plat-s3c24xx/devs.h>
45#include <asm/plat-s3c24xx/cpu.h>
46
47#include <asm/plat-s3c24xx/common-smdk.h>
48
49static struct map_desc smdk2443_iodesc[] __initdata = {
50 /* ISA IO Space map (memory space selected by A24) */
51
52 {
53 .virtual = (u32)S3C24XX_VA_ISA_WORD,
54 .pfn = __phys_to_pfn(S3C2410_CS2),
55 .length = 0x10000,
56 .type = MT_DEVICE,
57 }, {
58 .virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
59 .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
60 .length = SZ_4M,
61 .type = MT_DEVICE,
62 }, {
63 .virtual = (u32)S3C24XX_VA_ISA_BYTE,
64 .pfn = __phys_to_pfn(S3C2410_CS2),
65 .length = 0x10000,
66 .type = MT_DEVICE,
67 }, {
68 .virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
69 .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)),
70 .length = SZ_4M,
71 .type = MT_DEVICE,
72 }
73};
74
75#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
76#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
77#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
78
79static struct s3c2410_uartcfg smdk2443_uartcfgs[] __initdata = {
80 [0] = {
81 .hwport = 0,
82 .flags = 0,
83 .ucon = 0x3c5,
84 .ulcon = 0x03,
85 .ufcon = 0x51,
86 },
87 [1] = {
88 .hwport = 1,
89 .flags = 0,
90 .ucon = 0x3c5,
91 .ulcon = 0x03,
92 .ufcon = 0x51,
93 },
94 /* IR port */
95 [2] = {
96 .hwport = 2,
97 .flags = 0,
98 .ucon = 0x3c5,
99 .ulcon = 0x43,
100 .ufcon = 0x51,
101 }
102};
103
104static struct platform_device *smdk2443_devices[] __initdata = {
105 &s3c_device_wdt,
106 &s3c_device_i2c,
107};
108
109static struct s3c24xx_board smdk2443_board __initdata = {
110 .devices = smdk2443_devices,
111 .devices_count = ARRAY_SIZE(smdk2443_devices)
112};
113
114static void __init smdk2443_map_io(void)
115{
116 s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
117 s3c24xx_init_clocks(12000000);
118 s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
119 s3c24xx_set_board(&smdk2443_board);
120}
121
122static void __init smdk2443_machine_init(void)
123{
124 smdk_machine_init();
125}
126
127MACHINE_START(SMDK2443, "SMDK2443")
128 /* Maintainer: Ben Dooks <ben@fluff.org> */
129 .phys_io = S3C2410_PA_UART,
130 .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
131 .boot_params = S3C2410_SDRAM_PA + 0x100,
132
133 .init_irq = s3c24xx_init_irq,
134 .map_io = smdk2443_map_io,
135 .init_machine = smdk2443_machine_init,
136 .timer = &s3c24xx_timer,
137MACHINE_END
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
new file mode 100644
index 000000000000..11b1d0b310c3
--- /dev/null
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -0,0 +1,97 @@
1/* linux/arch/arm/mach-s3c2443/s3c2443.c
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Samsung S3C2443 Mobile CPU support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/interrupt.h>
16#include <linux/list.h>
17#include <linux/timer.h>
18#include <linux/init.h>
19#include <linux/platform_device.h>
20#include <linux/serial_core.h>
21#include <linux/sysdev.h>
22#include <linux/clk.h>
23
24#include <asm/mach/arch.h>
25#include <asm/mach/map.h>
26#include <asm/mach/irq.h>
27
28#include <asm/hardware.h>
29#include <asm/io.h>
30#include <asm/irq.h>
31
32#include <asm/arch/regs-s3c2443-clock.h>
33#include <asm/arch/reset.h>
34
35#include <asm/plat-s3c24xx/s3c2443.h>
36#include <asm/plat-s3c24xx/devs.h>
37#include <asm/plat-s3c24xx/cpu.h>
38
39static struct map_desc s3c2443_iodesc[] __initdata = {
40 IODESC_ENT(WATCHDOG),
41 IODESC_ENT(CLKPWR),
42 IODESC_ENT(TIMER),
43};
44
45struct sysdev_class s3c2443_sysclass = {
46 set_kset_name("s3c2443-core"),
47};
48
49static struct sys_device s3c2443_sysdev = {
50 .cls = &s3c2443_sysclass,
51};
52
53static void s3c2443_hard_reset(void)
54{
55 __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST);
56}
57
58int __init s3c2443_init(void)
59{
60 printk("S3C2443: Initialising architecture\n");
61
62 s3c24xx_reset_hook = s3c2443_hard_reset;
63
64 s3c_device_nand.name = "s3c2412-nand";
65
66 return sysdev_register(&s3c2443_sysdev);
67}
68
69void __init s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no)
70{
71 s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
72}
73
74/* s3c2443_map_io
75 *
76 * register the standard cpu IO areas, and any passed in from the
77 * machine specific initialisation.
78 */
79
80void __init s3c2443_map_io(struct map_desc *mach_desc, int mach_size)
81{
82 iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
83 iotable_init(mach_desc, mach_size);
84}
85
86/* need to register class before we actually register the device, and
87 * we also need to ensure that it has been initialised before any of the
88 * drivers even try to use it (even if not on an s3c2443 based system)
89 * as a driver which may support both 2443 and 2440 may try and use it.
90*/
91
92static int __init s3c2443_core_init(void)
93{
94 return sysdev_class_register(&s3c2443_sysclass);
95}
96
97core_initcall(s3c2443_core_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 27624447ec7d..4b277199d0e8 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -171,8 +171,8 @@ config CPU_ARM925T
171# ARM926T 171# ARM926T
172config CPU_ARM926T 172config CPU_ARM926T
173 bool "Support ARM926T processor" 173 bool "Support ARM926T processor"
174 depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_NS9XXX 174 depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
175 default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_NS9XXX 175 default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_NS9XXX
176 select CPU_32v5 176 select CPU_32v5
177 select CPU_ABRT_EV5TJ 177 select CPU_ABRT_EV5TJ
178 select CPU_CACHE_VIVT 178 select CPU_CACHE_VIVT
@@ -609,3 +609,10 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
609 Forget about fast user space cmpxchg support. 609 Forget about fast user space cmpxchg support.
610 It is just not possible. 610 It is just not possible.
611 611
612config OUTER_CACHE
613 bool
614 default n
615
616config CACHE_L2X0
617 bool
618 select OUTER_CACHE
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index d2f5672ecf62..2f8b95947774 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -66,3 +66,5 @@ obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o
66obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o 66obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o
67obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o 67obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o
68obj-$(CONFIG_CPU_V6) += proc-v6.o 68obj-$(CONFIG_CPU_V6) += proc-v6.o
69
70obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
new file mode 100644
index 000000000000..08a36f1b35d2
--- /dev/null
+++ b/arch/arm/mm/cache-l2x0.c
@@ -0,0 +1,104 @@
1/*
2 * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support
3 *
4 * Copyright (C) 2007 ARM Limited
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#include <linux/init.h>
20
21#include <asm/cacheflush.h>
22#include <asm/io.h>
23#include <asm/hardware/cache-l2x0.h>
24
25#define CACHE_LINE_SIZE 32
26
27static void __iomem *l2x0_base;
28
29static inline void sync_writel(unsigned long val, unsigned long reg,
30 unsigned long complete_mask)
31{
32 writel(val, l2x0_base + reg);
33 /* wait for the operation to complete */
34 while (readl(l2x0_base + reg) & complete_mask)
35 ;
36}
37
38static inline void cache_sync(void)
39{
40 sync_writel(0, L2X0_CACHE_SYNC, 1);
41}
42
43static inline void l2x0_inv_all(void)
44{
45 /* invalidate all ways */
46 sync_writel(0xff, L2X0_INV_WAY, 0xff);
47 cache_sync();
48}
49
50static void l2x0_inv_range(unsigned long start, unsigned long end)
51{
52 unsigned long addr;
53
54 start &= ~(CACHE_LINE_SIZE - 1);
55 for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
56 sync_writel(addr, L2X0_INV_LINE_PA, 1);
57 cache_sync();
58}
59
60static void l2x0_clean_range(unsigned long start, unsigned long end)
61{
62 unsigned long addr;
63
64 start &= ~(CACHE_LINE_SIZE - 1);
65 for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
66 sync_writel(addr, L2X0_CLEAN_LINE_PA, 1);
67 cache_sync();
68}
69
70static void l2x0_flush_range(unsigned long start, unsigned long end)
71{
72 unsigned long addr;
73
74 start &= ~(CACHE_LINE_SIZE - 1);
75 for (addr = start; addr < end; addr += CACHE_LINE_SIZE)
76 sync_writel(addr, L2X0_CLEAN_INV_LINE_PA, 1);
77 cache_sync();
78}
79
80void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
81{
82 __u32 aux;
83
84 l2x0_base = base;
85
86 /* disable L2X0 */
87 writel(0, l2x0_base + L2X0_CTRL);
88
89 aux = readl(l2x0_base + L2X0_AUX_CTRL);
90 aux &= aux_mask;
91 aux |= aux_val;
92 writel(aux, l2x0_base + L2X0_AUX_CTRL);
93
94 l2x0_inv_all();
95
96 /* enable L2X0 */
97 writel(1, l2x0_base + L2X0_CTRL);
98
99 outer_cache.inv_range = l2x0_inv_range;
100 outer_cache.clean_range = l2x0_clean_range;
101 outer_cache.flush_range = l2x0_flush_range;
102
103 printk(KERN_INFO "L2X0 cache controller enabled\n");
104}
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index 6a9c362fef5e..1f9f94f9af4b 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -205,9 +205,10 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
205 * kernel direct-mapped region for device DMA. 205 * kernel direct-mapped region for device DMA.
206 */ 206 */
207 { 207 {
208 unsigned long kaddr = (unsigned long)page_address(page); 208 void *ptr = page_address(page);
209 memset(page_address(page), 0, size); 209 memset(ptr, 0, size);
210 dmac_flush_range(kaddr, kaddr + size); 210 dmac_flush_range(ptr, ptr + size);
211 outer_flush_range(__pa(ptr), __pa(ptr) + size);
211 } 212 }
212 213
213 /* 214 /*
@@ -480,20 +481,24 @@ core_initcall(consistent_init);
480 * platforms with CONFIG_DMABOUNCE. 481 * platforms with CONFIG_DMABOUNCE.
481 * Use the driver DMA support - see dma-mapping.h (dma_sync_*) 482 * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
482 */ 483 */
483void consistent_sync(void *vaddr, size_t size, int direction) 484void consistent_sync(const void *start, size_t size, int direction)
484{ 485{
485 unsigned long start = (unsigned long)vaddr; 486 const void *end = start + size;
486 unsigned long end = start + size; 487
488 BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(end - 1));
487 489
488 switch (direction) { 490 switch (direction) {
489 case DMA_FROM_DEVICE: /* invalidate only */ 491 case DMA_FROM_DEVICE: /* invalidate only */
490 dmac_inv_range(start, end); 492 dmac_inv_range(start, end);
493 outer_inv_range(__pa(start), __pa(end));
491 break; 494 break;
492 case DMA_TO_DEVICE: /* writeback only */ 495 case DMA_TO_DEVICE: /* writeback only */
493 dmac_clean_range(start, end); 496 dmac_clean_range(start, end);
497 outer_clean_range(__pa(start), __pa(end));
494 break; 498 break;
495 case DMA_BIDIRECTIONAL: /* writeback and invalidate */ 499 case DMA_BIDIRECTIONAL: /* writeback and invalidate */
496 dmac_flush_range(start, end); 500 dmac_flush_range(start, end);
501 outer_flush_range(__pa(start), __pa(end));
497 break; 502 break;
498 default: 503 default:
499 BUG(); 504 BUG();
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index 79e800202424..9da43a0fdcdf 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -19,7 +19,8 @@ unsigned int cpu_last_asid = { 1 << ASID_BITS };
19/* 19/*
20 * We fork()ed a process, and we need a new context for the child 20 * We fork()ed a process, and we need a new context for the child
21 * to run in. We reserve version 0 for initial tasks so we will 21 * to run in. We reserve version 0 for initial tasks so we will
22 * always allocate an ASID. 22 * always allocate an ASID. The ASID 0 is reserved for the TTBR
23 * register changing sequence.
23 */ 24 */
24void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) 25void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
25{ 26{
@@ -38,8 +39,15 @@ void __new_context(struct mm_struct *mm)
38 * If we've used up all our ASIDs, we need 39 * If we've used up all our ASIDs, we need
39 * to start a new version and flush the TLB. 40 * to start a new version and flush the TLB.
40 */ 41 */
41 if ((asid & ~ASID_MASK) == 0) 42 if ((asid & ~ASID_MASK) == 0) {
43 asid = ++cpu_last_asid;
44 /* set the reserved ASID before flushing the TLB */
45 asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n"
46 :
47 : "r" (0));
48 isb();
42 flush_tlb_all(); 49 flush_tlb_all();
50 }
43 51
44 mm->context.id = asid; 52 mm->context.id = asid;
45} 53}
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index cf95c5d0ce4c..44558d5f9313 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -119,8 +119,6 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigne
119 flush_cache_page(vma, addr, pfn); 119 flush_cache_page(vma, addr, pfn);
120} 120}
121 121
122void __flush_dcache_page(struct address_space *mapping, struct page *page);
123
124/* 122/*
125 * Take care of architecture specific things when placing a new PTE into 123 * Take care of architecture specific things when placing a new PTE into
126 * a page table, or changing an existing PTE. Basically, there are two 124 * a page table, or changing an existing PTE. Basically, there are two
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 655c8376f0b5..94fd4bf5cb9e 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -49,8 +49,10 @@ pmd_t *top_pmd;
49 49
50static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK; 50static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
51static unsigned int ecc_mask __initdata = 0; 51static unsigned int ecc_mask __initdata = 0;
52pgprot_t pgprot_user;
52pgprot_t pgprot_kernel; 53pgprot_t pgprot_kernel;
53 54
55EXPORT_SYMBOL(pgprot_user);
54EXPORT_SYMBOL(pgprot_kernel); 56EXPORT_SYMBOL(pgprot_kernel);
55 57
56struct cachepolicy { 58struct cachepolicy {
@@ -345,6 +347,7 @@ static void __init build_mem_type_table(void)
345 mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1); 347 mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
346 } 348 }
347 349
350 pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
348 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | 351 pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
349 L_PTE_DIRTY | L_PTE_WRITE | 352 L_PTE_DIRTY | L_PTE_WRITE |
350 L_PTE_EXEC | kern_pgprot); 353 L_PTE_EXEC | kern_pgprot);
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 7b1843befb9c..eb42e5b94863 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -14,10 +14,13 @@
14#include <asm/assembler.h> 14#include <asm/assembler.h>
15#include <asm/asm-offsets.h> 15#include <asm/asm-offsets.h>
16#include <asm/elf.h> 16#include <asm/elf.h>
17#include <asm/hardware/arm_scu.h>
18#include <asm/pgtable-hwdef.h> 17#include <asm/pgtable-hwdef.h>
19#include <asm/pgtable.h> 18#include <asm/pgtable.h>
20 19
20#ifdef CONFIG_SMP
21#include <asm/hardware/arm_scu.h>
22#endif
23
21#include "proc-macros.S" 24#include "proc-macros.S"
22 25
23#define D_CACHE_LINE_SIZE 32 26#define D_CACHE_LINE_SIZE 32
@@ -30,6 +33,12 @@
30#define TTB_RGN_WT (2 << 3) 33#define TTB_RGN_WT (2 << 3)
31#define TTB_RGN_WB (3 << 3) 34#define TTB_RGN_WB (3 << 3)
32 35
36#ifndef CONFIG_SMP
37#define TTB_FLAGS TTB_RGN_WBWA
38#else
39#define TTB_FLAGS TTB_RGN_WBWA|TTB_S
40#endif
41
33ENTRY(cpu_v6_proc_init) 42ENTRY(cpu_v6_proc_init)
34 mov pc, lr 43 mov pc, lr
35 44
@@ -92,9 +101,7 @@ ENTRY(cpu_v6_switch_mm)
92#ifdef CONFIG_MMU 101#ifdef CONFIG_MMU
93 mov r2, #0 102 mov r2, #0
94 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id 103 ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
95#ifdef CONFIG_SMP 104 orr r0, r0, #TTB_FLAGS
96 orr r0, r0, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
97#endif
98 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB 105 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
99 mcr p15, 0, r2, c7, c10, 4 @ drain write buffer 106 mcr p15, 0, r2, c7, c10, 4 @ drain write buffer
100 mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 107 mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
@@ -183,8 +190,7 @@ __v6_setup:
183 /* Set up the SCU on core 0 only */ 190 /* Set up the SCU on core 0 only */
184 mrc p15, 0, r0, c0, c0, 5 @ CPU core number 191 mrc p15, 0, r0, c0, c0, 5 @ CPU core number
185 ands r0, r0, #15 192 ands r0, r0, #15
186 moveq r0, #0x10000000 @ SCU_BASE 193 ldreq r0, =SCU_BASE
187 orreq r0, r0, #0x00100000
188 ldreq r5, [r0, #SCU_CTRL] 194 ldreq r5, [r0, #SCU_CTRL]
189 orreq r5, r5, #1 195 orreq r5, r5, #1
190 streq r5, [r0, #SCU_CTRL] 196 streq r5, [r0, #SCU_CTRL]
@@ -204,9 +210,7 @@ __v6_setup:
204#ifdef CONFIG_MMU 210#ifdef CONFIG_MMU
205 mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs 211 mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
206 mcr p15, 0, r0, c2, c0, 2 @ TTB control register 212 mcr p15, 0, r0, c2, c0, 2 @ TTB control register
207#ifdef CONFIG_SMP 213 orr r4, r4, #TTB_FLAGS
208 orr r4, r4, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable
209#endif
210 mcr p15, 0, r4, c2, c0, 1 @ load TTB1 214 mcr p15, 0, r4, c2, c0, 1 @ load TTB1
211#endif /* CONFIG_MMU */ 215#endif /* CONFIG_MMU */
212 adr r5, v6_crval 216 adr r5, v6_crval
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index 94a58455f346..d95921a2ab99 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -5,23 +5,23 @@
5 * Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> 5 * Current Maintainer: Lennert Buytenhek <buytenh@wantstofly.org>
6 * 6 *
7 * Copyright 2004 (C) Intel Corp. 7 * Copyright 2004 (C) Intel Corp.
8 * Copyright 2005 (c) MontaVista Software, Inc. 8 * Copyright 2005 (C) MontaVista Software, Inc.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 * 13 *
14 * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is an 14 * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is
15 * extension to Intel's original XScale core that adds the following 15 * an extension to Intel's original XScale core that adds the following
16 * features: 16 * features:
17 * 17 *
18 * - ARMv6 Supersections 18 * - ARMv6 Supersections
19 * - Low Locality Reference pages (replaces mini-cache) 19 * - Low Locality Reference pages (replaces mini-cache)
20 * - 36-bit addressing 20 * - 36-bit addressing
21 * - L2 cache 21 * - L2 cache
22 * - Cache-coherency if chipset supports it 22 * - Cache coherency if chipset supports it
23 * 23 *
24 * Based on orignal XScale code by Nicolas Pitre 24 * Based on original XScale code by Nicolas Pitre.
25 */ 25 */
26 26
27#include <linux/linkage.h> 27#include <linux/linkage.h>
@@ -42,12 +42,12 @@
42#define MAX_AREA_SIZE 32768 42#define MAX_AREA_SIZE 32768
43 43
44/* 44/*
45 * The cache line size of the I and D cache. 45 * The cache line size of the L1 I, L1 D and unified L2 cache.
46 */ 46 */
47#define CACHELINESIZE 32 47#define CACHELINESIZE 32
48 48
49/* 49/*
50 * The size of the data cache. 50 * The size of the L1 D cache.
51 */ 51 */
52#define CACHESIZE 32768 52#define CACHESIZE 32768
53 53
@@ -57,9 +57,9 @@
57#define L2_CACHE_ENABLE 1 57#define L2_CACHE_ENABLE 1
58 58
59/* 59/*
60 * This macro is used to wait for a CP15 write and is needed 60 * This macro is used to wait for a CP15 write and is needed when we
61 * when we have to ensure that the last operation to the co-pro 61 * have to ensure that the last operation to the coprocessor was
62 * was completed before continuing with operation. 62 * completed before continuing with operation.
63 */ 63 */
64 .macro cpwait_ret, lr, rd 64 .macro cpwait_ret, lr, rd
65 mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15 65 mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15
@@ -68,13 +68,13 @@
68 .endm 68 .endm
69 69
70/* 70/*
71 * This macro cleans & invalidates the entire xsc3 dcache by set & way. 71 * This macro cleans and invalidates the entire L1 D cache.
72 */ 72 */
73 73
74 .macro clean_d_cache rd, rs 74 .macro clean_d_cache rd, rs
75 mov \rd, #0x1f00 75 mov \rd, #0x1f00
76 orr \rd, \rd, #0x00e0 76 orr \rd, \rd, #0x00e0
771: mcr p15, 0, \rd, c7, c14, 2 @ clean/inv set/way 771: mcr p15, 0, \rd, c7, c14, 2 @ clean/invalidate L1 D line
78 adds \rd, \rd, #0x40000000 78 adds \rd, \rd, #0x40000000
79 bcc 1b 79 bcc 1b
80 subs \rd, \rd, #0x20 80 subs \rd, \rd, #0x20
@@ -119,15 +119,15 @@ ENTRY(cpu_xsc3_reset)
119 mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE 119 mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
120 msr cpsr_c, r1 @ reset CPSR 120 msr cpsr_c, r1 @ reset CPSR
121 mrc p15, 0, r1, c1, c0, 0 @ ctrl register 121 mrc p15, 0, r1, c1, c0, 0 @ ctrl register
122 bic r1, r1, #0x0086 @ ........B....CA.
123 bic r1, r1, #0x3900 @ ..VIZ..S........ 122 bic r1, r1, #0x3900 @ ..VIZ..S........
123 bic r1, r1, #0x0086 @ ........B....CA.
124 mcr p15, 0, r1, c1, c0, 0 @ ctrl register 124 mcr p15, 0, r1, c1, c0, 0 @ ctrl register
125 mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB 125 mcr p15, 0, ip, c7, c7, 0 @ invalidate L1 caches and BTB
126 bic r1, r1, #0x0001 @ ...............M 126 bic r1, r1, #0x0001 @ ...............M
127 mcr p15, 0, r1, c1, c0, 0 @ ctrl register 127 mcr p15, 0, r1, c1, c0, 0 @ ctrl register
128 @ CAUTION: MMU turned off from this point. We count on the pipeline 128 @ CAUTION: MMU turned off from this point. We count on the pipeline
129 @ already containing those two last instructions to survive. 129 @ already containing those two last instructions to survive.
130 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 130 mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
131 mov pc, r0 131 mov pc, r0
132 132
133/* 133/*
@@ -139,14 +139,12 @@ ENTRY(cpu_xsc3_reset)
139 * 139 *
140 * XScale supports clock switching, but using idle mode support 140 * XScale supports clock switching, but using idle mode support
141 * allows external hardware to react to system state changes. 141 * allows external hardware to react to system state changes.
142
143 MMG: Come back to this one.
144 */ 142 */
145 .align 5 143 .align 5
146 144
147ENTRY(cpu_xsc3_do_idle) 145ENTRY(cpu_xsc3_do_idle)
148 mov r0, #1 146 mov r0, #1
149 mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE 147 mcr p14, 0, r0, c7, c0, 0 @ go to idle
150 mov pc, lr 148 mov pc, lr
151 149
152/* ================================= CACHE ================================ */ 150/* ================================= CACHE ================================ */
@@ -171,9 +169,9 @@ ENTRY(xsc3_flush_kern_cache_all)
171__flush_whole_cache: 169__flush_whole_cache:
172 clean_d_cache r0, r1 170 clean_d_cache r0, r1
173 tst r2, #VM_EXEC 171 tst r2, #VM_EXEC
174 mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB 172 mcrne p15, 0, ip, c7, c5, 0 @ invalidate L1 I cache and BTB
175 mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer 173 mcrne p15, 0, ip, c7, c10, 4 @ data write barrier
176 mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush 174 mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
177 mov pc, lr 175 mov pc, lr
178 176
179/* 177/*
@@ -194,21 +192,21 @@ ENTRY(xsc3_flush_user_cache_range)
194 bhs __flush_whole_cache 192 bhs __flush_whole_cache
195 193
1961: tst r2, #VM_EXEC 1941: tst r2, #VM_EXEC
197 mcrne p15, 0, r0, c7, c5, 1 @ Invalidate I cache line 195 mcrne p15, 0, r0, c7, c5, 1 @ invalidate L1 I line
198 mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate D cache line 196 mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line
199 add r0, r0, #CACHELINESIZE 197 add r0, r0, #CACHELINESIZE
200 cmp r0, r1 198 cmp r0, r1
201 blo 1b 199 blo 1b
202 tst r2, #VM_EXEC 200 tst r2, #VM_EXEC
203 mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB 201 mcrne p15, 0, ip, c7, c5, 6 @ invalidate BTB
204 mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer 202 mcrne p15, 0, ip, c7, c10, 4 @ data write barrier
205 mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush 203 mcrne p15, 0, ip, c7, c5, 4 @ prefetch flush
206 mov pc, lr 204 mov pc, lr
207 205
208/* 206/*
209 * coherent_kern_range(start, end) 207 * coherent_kern_range(start, end)
210 * 208 *
211 * Ensure coherency between the Icache and the Dcache in the 209 * Ensure coherency between the I cache and the D cache in the
212 * region described by start. If you have non-snooping 210 * region described by start. If you have non-snooping
213 * Harvard caches, you need to implement this function. 211 * Harvard caches, you need to implement this function.
214 * 212 *
@@ -222,34 +220,34 @@ ENTRY(xsc3_coherent_kern_range)
222/* FALLTHROUGH */ 220/* FALLTHROUGH */
223ENTRY(xsc3_coherent_user_range) 221ENTRY(xsc3_coherent_user_range)
224 bic r0, r0, #CACHELINESIZE - 1 222 bic r0, r0, #CACHELINESIZE - 1
2251: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 2231: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
226 add r0, r0, #CACHELINESIZE 224 add r0, r0, #CACHELINESIZE
227 cmp r0, r1 225 cmp r0, r1
228 blo 1b 226 blo 1b
229 mov r0, #0 227 mov r0, #0
230 mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB 228 mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB
231 mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer 229 mcr p15, 0, r0, c7, c10, 4 @ data write barrier
232 mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush 230 mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
233 mov pc, lr 231 mov pc, lr
234 232
235/* 233/*
236 * flush_kern_dcache_page(void *page) 234 * flush_kern_dcache_page(void *page)
237 * 235 *
238 * Ensure no D cache aliasing occurs, either with itself or 236 * Ensure no D cache aliasing occurs, either with itself or
239 * the I cache 237 * the I cache.
240 * 238 *
241 * - addr - page aligned address 239 * - addr - page aligned address
242 */ 240 */
243ENTRY(xsc3_flush_kern_dcache_page) 241ENTRY(xsc3_flush_kern_dcache_page)
244 add r1, r0, #PAGE_SZ 242 add r1, r0, #PAGE_SZ
2451: mcr p15, 0, r0, c7, c14, 1 @ Clean/Invalidate D Cache line 2431: mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line
246 add r0, r0, #CACHELINESIZE 244 add r0, r0, #CACHELINESIZE
247 cmp r0, r1 245 cmp r0, r1
248 blo 1b 246 blo 1b
249 mov r0, #0 247 mov r0, #0
250 mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB 248 mcr p15, 0, r0, c7, c5, 0 @ invalidate L1 I cache and BTB
251 mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer 249 mcr p15, 0, r0, c7, c10, 4 @ data write barrier
252 mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush 250 mcr p15, 0, r0, c7, c5, 4 @ prefetch flush
253 mov pc, lr 251 mov pc, lr
254 252
255/* 253/*
@@ -266,17 +264,17 @@ ENTRY(xsc3_flush_kern_dcache_page)
266ENTRY(xsc3_dma_inv_range) 264ENTRY(xsc3_dma_inv_range)
267 tst r0, #CACHELINESIZE - 1 265 tst r0, #CACHELINESIZE - 1
268 bic r0, r0, #CACHELINESIZE - 1 266 bic r0, r0, #CACHELINESIZE - 1
269 mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D entry 267 mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D line
270 mcrne p15, 1, r0, c7, c11, 1 @ clean L2 D entry 268 mcrne p15, 1, r0, c7, c11, 1 @ clean L2 line
271 tst r1, #CACHELINESIZE - 1 269 tst r1, #CACHELINESIZE - 1
272 mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D entry 270 mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D line
273 mcrne p15, 1, r1, c7, c11, 1 @ clean L2 D entry 271 mcrne p15, 1, r1, c7, c11, 1 @ clean L2 line
2741: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D entry 2721: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D line
275 mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line 273 mcr p15, 1, r0, c7, c7, 1 @ invalidate L2 line
276 add r0, r0, #CACHELINESIZE 274 add r0, r0, #CACHELINESIZE
277 cmp r0, r1 275 cmp r0, r1
278 blo 1b 276 blo 1b
279 mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer 277 mcr p15, 0, r0, c7, c10, 4 @ data write barrier
280 mov pc, lr 278 mov pc, lr
281 279
282/* 280/*
@@ -289,12 +287,12 @@ ENTRY(xsc3_dma_inv_range)
289 */ 287 */
290ENTRY(xsc3_dma_clean_range) 288ENTRY(xsc3_dma_clean_range)
291 bic r0, r0, #CACHELINESIZE - 1 289 bic r0, r0, #CACHELINESIZE - 1
2921: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D entry 2901: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
293 mcr p15, 1, r0, c7, c11, 1 @ clean L2 D entry 291 mcr p15, 1, r0, c7, c11, 1 @ clean L2 line
294 add r0, r0, #CACHELINESIZE 292 add r0, r0, #CACHELINESIZE
295 cmp r0, r1 293 cmp r0, r1
296 blo 1b 294 blo 1b
297 mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer 295 mcr p15, 0, r0, c7, c10, 4 @ data write barrier
298 mov pc, lr 296 mov pc, lr
299 297
300/* 298/*
@@ -307,13 +305,13 @@ ENTRY(xsc3_dma_clean_range)
307 */ 305 */
308ENTRY(xsc3_dma_flush_range) 306ENTRY(xsc3_dma_flush_range)
309 bic r0, r0, #CACHELINESIZE - 1 307 bic r0, r0, #CACHELINESIZE - 1
3101: mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate L1 D cache line 3081: mcr p15, 0, r0, c7, c14, 1 @ clean/invalidate L1 D line
311 mcr p15, 1, r0, c7, c11, 1 @ Clean L2 D cache line 309 mcr p15, 1, r0, c7, c11, 1 @ clean L2 line
312 mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line 310 mcr p15, 1, r0, c7, c7, 1 @ invalidate L2 line
313 add r0, r0, #CACHELINESIZE 311 add r0, r0, #CACHELINESIZE
314 cmp r0, r1 312 cmp r0, r1
315 blo 1b 313 blo 1b
316 mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer 314 mcr p15, 0, r0, c7, c10, 4 @ data write barrier
317 mov pc, lr 315 mov pc, lr
318 316
319ENTRY(xsc3_cache_fns) 317ENTRY(xsc3_cache_fns)
@@ -328,7 +326,7 @@ ENTRY(xsc3_cache_fns)
328 .long xsc3_dma_flush_range 326 .long xsc3_dma_flush_range
329 327
330ENTRY(cpu_xsc3_dcache_clean_area) 328ENTRY(cpu_xsc3_dcache_clean_area)
3311: mcr p15, 0, r0, c7, c10, 1 @ clean D entry 3291: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
332 add r0, r0, #CACHELINESIZE 330 add r0, r0, #CACHELINESIZE
333 subs r1, r1, #CACHELINESIZE 331 subs r1, r1, #CACHELINESIZE
334 bhi 1b 332 bhi 1b
@@ -346,14 +344,14 @@ ENTRY(cpu_xsc3_dcache_clean_area)
346 .align 5 344 .align 5
347ENTRY(cpu_xsc3_switch_mm) 345ENTRY(cpu_xsc3_switch_mm)
348 clean_d_cache r1, r2 346 clean_d_cache r1, r2
349 mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB 347 mcr p15, 0, ip, c7, c5, 0 @ invalidate L1 I cache and BTB
350 mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer 348 mcr p15, 0, ip, c7, c10, 4 @ data write barrier
351 mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush 349 mcr p15, 0, ip, c7, c5, 4 @ prefetch flush
352#ifdef L2_CACHE_ENABLE 350#ifdef L2_CACHE_ENABLE
353 orr r0, r0, #0x18 @ cache the page table in L2 351 orr r0, r0, #0x18 @ cache the page table in L2
354#endif 352#endif
355 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer 353 mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
356 mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs 354 mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
357 cpwait_ret lr, ip 355 cpwait_ret lr, ip
358 356
359/* 357/*
@@ -366,34 +364,34 @@ ENTRY(cpu_xsc3_switch_mm)
366ENTRY(cpu_xsc3_set_pte_ext) 364ENTRY(cpu_xsc3_set_pte_ext)
367 str r1, [r0], #-2048 @ linux version 365 str r1, [r0], #-2048 @ linux version
368 366
369 bic r2, r1, #0xff0 @ Keep C, B bits 367 bic r2, r1, #0xff0 @ keep C, B bits
370 orr r2, r2, #PTE_TYPE_EXT @ extended page 368 orr r2, r2, #PTE_TYPE_EXT @ extended page
371 tst r1, #L_PTE_SHARED @ Shared? 369 tst r1, #L_PTE_SHARED @ shared?
372 orrne r2, r2, #0x200 370 orrne r2, r2, #0x200
373 371
374 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY 372 eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
375 373
376 tst r3, #L_PTE_USER @ User? 374 tst r3, #L_PTE_USER @ user?
377 orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w 375 orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w
378 376
379 tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? 377 tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ write and dirty?
380 orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w 378 orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w
381 @ combined with user -> user r/w 379 @ combined with user -> user r/w
382 380
383#if L2_CACHE_ENABLE 381#if L2_CACHE_ENABLE
384 @ If its cacheable it needs to be in L2 also. 382 @ If it's cacheable, it needs to be in L2 also.
385 eor ip, r1, #L_PTE_CACHEABLE 383 eor ip, r1, #L_PTE_CACHEABLE
386 tst ip, #L_PTE_CACHEABLE 384 tst ip, #L_PTE_CACHEABLE
387 orreq r2, r2, #PTE_EXT_TEX(0x5) 385 orreq r2, r2, #PTE_EXT_TEX(0x5)
388#endif 386#endif
389 387
390 tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? 388 tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ present and young?
391 movne r2, #0 @ no -> fault 389 movne r2, #0 @ no -> fault
392 390
393 str r2, [r0] @ hardware version 391 str r2, [r0] @ hardware version
394 mov ip, #0 392 mov ip, #0
395 mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr 393 mcr p15, 0, r0, c7, c10, 1 @ clean L1 D line
396 mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer 394 mcr p15, 0, ip, c7, c10, 4 @ data write barrier
397 mov pc, lr 395 mov pc, lr
398 396
399 .ltorg 397 .ltorg
@@ -406,17 +404,18 @@ ENTRY(cpu_xsc3_set_pte_ext)
406__xsc3_setup: 404__xsc3_setup:
407 mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE 405 mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE
408 msr cpsr_c, r0 406 msr cpsr_c, r0
409 mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB 407 mcr p15, 0, ip, c7, c7, 0 @ invalidate L1 caches and BTB
410 mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer 408 mcr p15, 0, ip, c7, c10, 4 @ data write barrier
411 mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush 409 mcr p15, 0, ip, c7, c5, 4 @ prefetch flush
412 mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs 410 mcr p15, 0, ip, c8, c7, 0 @ invalidate I and D TLBs
413#if L2_CACHE_ENABLE 411#if L2_CACHE_ENABLE
414 orr r4, r4, #0x18 @ cache the page table in L2 412 orr r4, r4, #0x18 @ cache the page table in L2
415#endif 413#endif
416 mcr p15, 0, r4, c2, c0, 0 @ load page table pointer 414 mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
417 mov r0, #1 @ Allow access to CP0 and CP13 415
418 orr r0, r0, #1 << 13 @ Its undefined whether this 416 mov r0, #0 @ don't allow CP access
419 mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes 417 mcr p15, 0, r0, c15, c1, 0 @ write CP access register
418
420 mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg 419 mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg
421 and r0, r0, #2 @ preserve bit P bit setting 420 and r0, r0, #2 @ preserve bit P bit setting
422#if L2_CACHE_ENABLE 421#if L2_CACHE_ENABLE
@@ -427,9 +426,9 @@ __xsc3_setup:
427 adr r5, xsc3_crval 426 adr r5, xsc3_crval
428 ldmia r5, {r5, r6} 427 ldmia r5, {r5, r6}
429 mrc p15, 0, r0, c1, c0, 0 @ get control register 428 mrc p15, 0, r0, c1, c0, 0 @ get control register
430 bic r0, r0, r5 @ .... .... .... ..A. 429 bic r0, r0, r5 @ ..V. ..R. .... ..A.
431 orr r0, r0, r6 @ .... .... .... .C.M 430 orr r0, r0, r6 @ ..VI Z..S .... .C.M (mmu)
432 orr r0, r0, #0x00000800 @ ..VI Z..S .... .... 431 @ ...I Z..S .... .... (uc)
433#if L2_CACHE_ENABLE 432#if L2_CACHE_ENABLE
434 orr r0, r0, #0x04000000 @ L2 enable 433 orr r0, r0, #0x04000000 @ L2 enable
435#endif 434#endif
@@ -439,7 +438,7 @@ __xsc3_setup:
439 438
440 .type xsc3_crval, #object 439 .type xsc3_crval, #object
441xsc3_crval: 440xsc3_crval:
442 crval clear=0x04003b02, mmuset=0x00003105, ucset=0x00001100 441 crval clear=0x04002202, mmuset=0x00003905, ucset=0x00001900
443 442
444 __INITDATA 443 __INITDATA
445 444
@@ -474,7 +473,7 @@ cpu_elf_name:
474 473
475 .type cpu_xsc3_name, #object 474 .type cpu_xsc3_name, #object
476cpu_xsc3_name: 475cpu_xsc3_name:
477 .asciz "XScale-Core3" 476 .asciz "XScale-V3 based processor"
478 .size cpu_xsc3_name, . - cpu_xsc3_name 477 .size cpu_xsc3_name, . - cpu_xsc3_name
479 478
480 .align 479 .align
@@ -490,7 +489,7 @@ __xsc3_proc_info:
490 PMD_SECT_CACHEABLE | \ 489 PMD_SECT_CACHEABLE | \
491 PMD_SECT_AP_WRITE | \ 490 PMD_SECT_AP_WRITE | \
492 PMD_SECT_AP_READ 491 PMD_SECT_AP_READ
493 .long PMD_TYPE_SECT | \ 492 .long PMD_TYPE_SECT | \
494 PMD_SECT_AP_WRITE | \ 493 PMD_SECT_AP_WRITE | \
495 PMD_SECT_AP_READ 494 PMD_SECT_AP_READ
496 b __xsc3_setup 495 b __xsc3_setup
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index fd6adde39091..20f84bbaa9bb 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -53,6 +53,8 @@ ENTRY(v6wbi_flush_user_tlb_range)
53 add r0, r0, #PAGE_SZ 53 add r0, r0, #PAGE_SZ
54 cmp r0, r1 54 cmp r0, r1
55 blo 1b 55 blo 1b
56 mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB
57 mcr p15, 0, ip, c7, c10, 4 @ data synchronization barrier
56 mov pc, lr 58 mov pc, lr
57 59
58/* 60/*
@@ -80,7 +82,9 @@ ENTRY(v6wbi_flush_kern_tlb_range)
80 add r0, r0, #PAGE_SZ 82 add r0, r0, #PAGE_SZ
81 cmp r0, r1 83 cmp r0, r1
82 blo 1b 84 blo 1b
85 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
83 mcr p15, 0, r2, c7, c10, 4 @ data synchronization barrier 86 mcr p15, 0, r2, c7, c10, 4 @ data synchronization barrier
87 mcr p15, 0, r2, c7, c5, 4 @ prefetch flush
84 mov pc, lr 88 mov pc, lr
85 89
86 .section ".text.init", #alloc, #execinstr 90 .section ".text.init", #alloc, #execinstr
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
new file mode 100644
index 000000000000..e22343160634
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -0,0 +1,99 @@
1# arch/arm/plat-s3c24xx/Kconfig
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7config PLAT_S3C24XX
8 bool
9 depends on ARCH_S3C2410
10 default y if ARCH_S3C2410
11 help
12 Base platform code for any Samsung S3C device
13
14if PLAT_S3C24XX
15
16config CPU_S3C244X
17 bool
18 depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
19 help
20 Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
21
22config PM_SIMTEC
23 bool
24 help
25 Common power management code for systems that are
26 compatible with the Simtec style of power management
27
28config S3C2410_BOOT_WATCHDOG
29 bool "S3C2410 Initialisation watchdog"
30 depends on ARCH_S3C2410 && S3C2410_WATCHDOG
31 help
32 Say y to enable the watchdog during the kernel decompression
33 stage. If the kernel fails to uncompress, then the watchdog
34 will trigger a reset and the system should restart.
35
36config S3C2410_BOOT_ERROR_RESET
37 bool "S3C2410 Reboot on decompression error"
38 depends on ARCH_S3C2410
39 help
40 Say y here to use the watchdog to reset the system if the
41 kernel decompressor detects an error during decompression.
42
43config S3C2410_PM_DEBUG
44 bool "S3C2410 PM Suspend debug"
45 depends on ARCH_S3C2410 && PM
46 help
47 Say Y here if you want verbose debugging from the PM Suspend and
48 Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
49 for more information.
50
51config S3C2410_PM_CHECK
52 bool "S3C2410 PM Suspend Memory CRC"
53 depends on ARCH_S3C2410 && PM && CRC32
54 help
55 Enable the PM code's memory area checksum over sleep. This option
56 will generate CRCs of all blocks of memory, and store them before
57 going to sleep. The blocks are then checked on resume for any
58 errors.
59
60config S3C2410_PM_CHECK_CHUNKSIZE
61 int "S3C2410 PM Suspend CRC Chunksize (KiB)"
62 depends on ARCH_S3C2410 && PM && S3C2410_PM_CHECK
63 default 64
64 help
65 Set the chunksize in Kilobytes of the CRC for checking memory
66 corruption over suspend and resume. A smaller value will mean that
67 the CRC data block will take more memory, but wil identify any
68 faults with better precision.
69
70config S3C2410_LOWLEVEL_UART_PORT
71 int "S3C2410 UART to use for low-level messages"
72 default 0
73 help
74 Choice of which UART port to use for the low-level messages,
75 such as the `Uncompressing...` at start time. The value of
76 this configuration should be between zero and two. The port
77 must have been initialised by the boot-loader before use.
78
79config S3C2410_DMA
80 bool "S3C2410 DMA support"
81 depends on ARCH_S3C2410
82 help
83 S3C2410 DMA support. This is needed for drivers like sound which
84 use the S3C2410's DMA system to move data to and from the
85 peripheral blocks.
86
87config S3C2410_DMA_DEBUG
88 bool "S3C2410 DMA support debug"
89 depends on ARCH_S3C2410 && S3C2410_DMA
90 help
91 Enable debugging output for the DMA code. This option sends info
92 to the kernel log, at priority KERN_DEBUG.
93
94config MACH_SMDK
95 bool
96 help
97 Common machine code for SMDK2410 and SMDK2440
98
99endif
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
new file mode 100644
index 000000000000..8e5ccaa1f03c
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -0,0 +1,30 @@
1# arch/arm/plat-s3c24xx/Makefile
2#
3# Copyright 2007 Simtec Electronics
4#
5# Licensed under GPLv2
6
7obj-y :=
8obj-m :=
9obj-n :=
10obj- :=
11
12
13# Core files
14
15obj-y += cpu.o
16obj-y += irq.o
17obj-y += devs.o
18obj-y += gpio.o
19obj-y += time.o
20obj-y += clock.o
21
22# Architecture dependant builds
23
24obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
25obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o
26obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
27obj-$(CONFIG_PM) += pm.o
28obj-$(CONFIG_PM) += sleep.o
29obj-$(CONFIG_S3C2410_DMA) += dma.o
30obj-$(CONFIG_MACH_SMDK) += common-smdk.o
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c
new file mode 100644
index 000000000000..d3dc03a7383a
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/clock.c
@@ -0,0 +1,449 @@
1/* linux/arch/arm/plat-s3c24xx/clock.c
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C24XX Core clock control support
7 *
8 * Based on, and code from linux/arch/arm/mach-versatile/clock.c
9 **
10 ** Copyright (C) 2004 ARM Limited.
11 ** Written by Deep Blue Solutions Limited.
12 *
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27*/
28
29#include <linux/init.h>
30#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/list.h>
33#include <linux/errno.h>
34#include <linux/err.h>
35#include <linux/platform_device.h>
36#include <linux/sysdev.h>
37#include <linux/interrupt.h>
38#include <linux/ioport.h>
39#include <linux/clk.h>
40#include <linux/mutex.h>
41#include <linux/delay.h>
42
43#include <asm/hardware.h>
44#include <asm/irq.h>
45#include <asm/io.h>
46
47#include <asm/arch/regs-clock.h>
48#include <asm/arch/regs-gpio.h>
49
50#include <asm/plat-s3c24xx/clock.h>
51#include <asm/plat-s3c24xx/cpu.h>
52
53/* clock information */
54
55static LIST_HEAD(clocks);
56
57DEFINE_MUTEX(clocks_mutex);
58
59/* enable and disable calls for use with the clk struct */
60
61static int clk_null_enable(struct clk *clk, int enable)
62{
63 return 0;
64}
65
66/* Clock API calls */
67
68struct clk *clk_get(struct device *dev, const char *id)
69{
70 struct clk *p;
71 struct clk *clk = ERR_PTR(-ENOENT);
72 int idno;
73
74 if (dev == NULL || dev->bus != &platform_bus_type)
75 idno = -1;
76 else
77 idno = to_platform_device(dev)->id;
78
79 mutex_lock(&clocks_mutex);
80
81 list_for_each_entry(p, &clocks, list) {
82 if (p->id == idno &&
83 strcmp(id, p->name) == 0 &&
84 try_module_get(p->owner)) {
85 clk = p;
86 break;
87 }
88 }
89
90 /* check for the case where a device was supplied, but the
91 * clock that was being searched for is not device specific */
92
93 if (IS_ERR(clk)) {
94 list_for_each_entry(p, &clocks, list) {
95 if (p->id == -1 && strcmp(id, p->name) == 0 &&
96 try_module_get(p->owner)) {
97 clk = p;
98 break;
99 }
100 }
101 }
102
103 mutex_unlock(&clocks_mutex);
104 return clk;
105}
106
107void clk_put(struct clk *clk)
108{
109 module_put(clk->owner);
110}
111
112int clk_enable(struct clk *clk)
113{
114 if (IS_ERR(clk) || clk == NULL)
115 return -EINVAL;
116
117 clk_enable(clk->parent);
118
119 mutex_lock(&clocks_mutex);
120
121 if ((clk->usage++) == 0)
122 (clk->enable)(clk, 1);
123
124 mutex_unlock(&clocks_mutex);
125 return 0;
126}
127
128void clk_disable(struct clk *clk)
129{
130 if (IS_ERR(clk) || clk == NULL)
131 return;
132
133 mutex_lock(&clocks_mutex);
134
135 if ((--clk->usage) == 0)
136 (clk->enable)(clk, 0);
137
138 mutex_unlock(&clocks_mutex);
139 clk_disable(clk->parent);
140}
141
142
143unsigned long clk_get_rate(struct clk *clk)
144{
145 if (IS_ERR(clk))
146 return 0;
147
148 if (clk->rate != 0)
149 return clk->rate;
150
151 if (clk->get_rate != NULL)
152 return (clk->get_rate)(clk);
153
154 if (clk->parent != NULL)
155 return clk_get_rate(clk->parent);
156
157 return clk->rate;
158}
159
160long clk_round_rate(struct clk *clk, unsigned long rate)
161{
162 if (!IS_ERR(clk) && clk->round_rate)
163 return (clk->round_rate)(clk, rate);
164
165 return rate;
166}
167
168int clk_set_rate(struct clk *clk, unsigned long rate)
169{
170 int ret;
171
172 if (IS_ERR(clk))
173 return -EINVAL;
174
175 mutex_lock(&clocks_mutex);
176 ret = (clk->set_rate)(clk, rate);
177 mutex_unlock(&clocks_mutex);
178
179 return ret;
180}
181
182struct clk *clk_get_parent(struct clk *clk)
183{
184 return clk->parent;
185}
186
187int clk_set_parent(struct clk *clk, struct clk *parent)
188{
189 int ret = 0;
190
191 if (IS_ERR(clk))
192 return -EINVAL;
193
194 mutex_lock(&clocks_mutex);
195
196 if (clk->set_parent)
197 ret = (clk->set_parent)(clk, parent);
198
199 mutex_unlock(&clocks_mutex);
200
201 return ret;
202}
203
204EXPORT_SYMBOL(clk_get);
205EXPORT_SYMBOL(clk_put);
206EXPORT_SYMBOL(clk_enable);
207EXPORT_SYMBOL(clk_disable);
208EXPORT_SYMBOL(clk_get_rate);
209EXPORT_SYMBOL(clk_round_rate);
210EXPORT_SYMBOL(clk_set_rate);
211EXPORT_SYMBOL(clk_get_parent);
212EXPORT_SYMBOL(clk_set_parent);
213
214/* base clocks */
215
216struct clk clk_xtal = {
217 .name = "xtal",
218 .id = -1,
219 .rate = 0,
220 .parent = NULL,
221 .ctrlbit = 0,
222};
223
224struct clk clk_mpll = {
225 .name = "mpll",
226 .id = -1,
227};
228
229struct clk clk_upll = {
230 .name = "upll",
231 .id = -1,
232 .parent = NULL,
233 .ctrlbit = 0,
234};
235
236struct clk clk_f = {
237 .name = "fclk",
238 .id = -1,
239 .rate = 0,
240 .parent = &clk_mpll,
241 .ctrlbit = 0,
242};
243
244struct clk clk_h = {
245 .name = "hclk",
246 .id = -1,
247 .rate = 0,
248 .parent = NULL,
249 .ctrlbit = 0,
250};
251
252struct clk clk_p = {
253 .name = "pclk",
254 .id = -1,
255 .rate = 0,
256 .parent = NULL,
257 .ctrlbit = 0,
258};
259
260struct clk clk_usb_bus = {
261 .name = "usb-bus",
262 .id = -1,
263 .rate = 0,
264 .parent = &clk_upll,
265};
266
267/* clocks that could be registered by external code */
268
269static int s3c24xx_dclk_enable(struct clk *clk, int enable)
270{
271 unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
272
273 if (enable)
274 dclkcon |= clk->ctrlbit;
275 else
276 dclkcon &= ~clk->ctrlbit;
277
278 __raw_writel(dclkcon, S3C24XX_DCLKCON);
279
280 return 0;
281}
282
283static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent)
284{
285 unsigned long dclkcon;
286 unsigned int uclk;
287
288 if (parent == &clk_upll)
289 uclk = 1;
290 else if (parent == &clk_p)
291 uclk = 0;
292 else
293 return -EINVAL;
294
295 clk->parent = parent;
296
297 dclkcon = __raw_readl(S3C24XX_DCLKCON);
298
299 if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
300 if (uclk)
301 dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK;
302 else
303 dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK;
304 } else {
305 if (uclk)
306 dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK;
307 else
308 dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
309 }
310
311 __raw_writel(dclkcon, S3C24XX_DCLKCON);
312
313 return 0;
314}
315
316
317static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
318{
319 unsigned long mask;
320 unsigned long source;
321
322 /* calculate the MISCCR setting for the clock */
323
324 if (parent == &clk_xtal)
325 source = S3C2410_MISCCR_CLK0_MPLL;
326 else if (parent == &clk_upll)
327 source = S3C2410_MISCCR_CLK0_UPLL;
328 else if (parent == &clk_f)
329 source = S3C2410_MISCCR_CLK0_FCLK;
330 else if (parent == &clk_h)
331 source = S3C2410_MISCCR_CLK0_HCLK;
332 else if (parent == &clk_p)
333 source = S3C2410_MISCCR_CLK0_PCLK;
334 else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0)
335 source = S3C2410_MISCCR_CLK0_DCLK0;
336 else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1)
337 source = S3C2410_MISCCR_CLK0_DCLK0;
338 else
339 return -EINVAL;
340
341 clk->parent = parent;
342
343 if (clk == &s3c24xx_dclk0)
344 mask = S3C2410_MISCCR_CLK0_MASK;
345 else {
346 source <<= 4;
347 mask = S3C2410_MISCCR_CLK1_MASK;
348 }
349
350 s3c2410_modify_misccr(mask, source);
351 return 0;
352}
353
354/* external clock definitions */
355
356struct clk s3c24xx_dclk0 = {
357 .name = "dclk0",
358 .id = -1,
359 .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
360 .enable = s3c24xx_dclk_enable,
361 .set_parent = s3c24xx_dclk_setparent,
362};
363
364struct clk s3c24xx_dclk1 = {
365 .name = "dclk1",
366 .id = -1,
367 .ctrlbit = S3C2410_DCLKCON_DCLK0EN,
368 .enable = s3c24xx_dclk_enable,
369 .set_parent = s3c24xx_dclk_setparent,
370};
371
372struct clk s3c24xx_clkout0 = {
373 .name = "clkout0",
374 .id = -1,
375 .set_parent = s3c24xx_clkout_setparent,
376};
377
378struct clk s3c24xx_clkout1 = {
379 .name = "clkout1",
380 .id = -1,
381 .set_parent = s3c24xx_clkout_setparent,
382};
383
384struct clk s3c24xx_uclk = {
385 .name = "uclk",
386 .id = -1,
387};
388
389/* initialise the clock system */
390
391int s3c24xx_register_clock(struct clk *clk)
392{
393 clk->owner = THIS_MODULE;
394
395 if (clk->enable == NULL)
396 clk->enable = clk_null_enable;
397
398 /* add to the list of available clocks */
399
400 mutex_lock(&clocks_mutex);
401 list_add(&clk->list, &clocks);
402 mutex_unlock(&clocks_mutex);
403
404 return 0;
405}
406
407/* initalise all the clocks */
408
409int __init s3c24xx_setup_clocks(unsigned long xtal,
410 unsigned long fclk,
411 unsigned long hclk,
412 unsigned long pclk)
413{
414 printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
415
416 /* initialise the main system clocks */
417
418 clk_xtal.rate = xtal;
419 clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
420
421 clk_mpll.rate = fclk;
422 clk_h.rate = hclk;
423 clk_p.rate = pclk;
424 clk_f.rate = fclk;
425
426 /* assume uart clocks are correctly setup */
427
428 /* register our clocks */
429
430 if (s3c24xx_register_clock(&clk_xtal) < 0)
431 printk(KERN_ERR "failed to register master xtal\n");
432
433 if (s3c24xx_register_clock(&clk_mpll) < 0)
434 printk(KERN_ERR "failed to register mpll clock\n");
435
436 if (s3c24xx_register_clock(&clk_upll) < 0)
437 printk(KERN_ERR "failed to register upll clock\n");
438
439 if (s3c24xx_register_clock(&clk_f) < 0)
440 printk(KERN_ERR "failed to register cpu fclk\n");
441
442 if (s3c24xx_register_clock(&clk_h) < 0)
443 printk(KERN_ERR "failed to register cpu hclk\n");
444
445 if (s3c24xx_register_clock(&clk_p) < 0)
446 printk(KERN_ERR "failed to register cpu pclk\n");
447
448 return 0;
449}
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c
index a40eaa656177..908efa7d745f 100644
--- a/arch/arm/mach-s3c2410/common-smdk.c
+++ b/arch/arm/plat-s3c24xx/common-smdk.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/common-smdk.c 1/* linux/arch/arm/plat-s3c24xx/common-smdk.c
2 * 2 *
3 * Copyright (c) 2006 Simtec Electronics 3 * Copyright (c) 2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -38,9 +38,9 @@
38 38
39#include <asm/arch/nand.h> 39#include <asm/arch/nand.h>
40 40
41#include "common-smdk.h" 41#include <asm/plat-s3c24xx/common-smdk.h>
42#include "devs.h" 42#include <asm/plat-s3c24xx/devs.h>
43#include "pm.h" 43#include <asm/plat-s3c24xx/pm.h>
44 44
45/* LED devices */ 45/* LED devices */
46 46
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/plat-s3c24xx/cpu.c
index ae1f5bb63f7a..6a2d1070e5a0 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/plat-s3c24xx/cpu.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/cpu.c 1/* linux/arch/arm/plat-s3c24xx/cpu.c
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2004-2005 Simtec Electronics
4 * http://www.simtec.co.uk/products/SWLINUX/ 4 * http://www.simtec.co.uk/products/SWLINUX/
@@ -40,15 +40,16 @@
40#include <asm/arch/regs-gpio.h> 40#include <asm/arch/regs-gpio.h>
41#include <asm/arch/regs-serial.h> 41#include <asm/arch/regs-serial.h>
42 42
43#include "cpu.h" 43#include <asm/plat-s3c24xx/cpu.h>
44#include "devs.h" 44#include <asm/plat-s3c24xx/devs.h>
45#include "clock.h" 45#include <asm/plat-s3c24xx/clock.h>
46#include "s3c2400.h" 46#include <asm/plat-s3c24xx/s3c2400.h>
47#include "s3c2410.h" 47#include <asm/plat-s3c24xx/s3c2410.h>
48#include "s3c2412.h" 48#include <asm/plat-s3c24xx/s3c2412.h>
49#include "s3c244x.h" 49#include "s3c244x.h"
50#include "s3c2440.h" 50#include <asm/plat-s3c24xx/s3c2440.h>
51#include "s3c2442.h" 51#include <asm/plat-s3c24xx/s3c2442.h>
52#include <asm/plat-s3c24xx/s3c2443.h>
52 53
53struct cpu_table { 54struct cpu_table {
54 unsigned long idcode; 55 unsigned long idcode;
@@ -67,6 +68,7 @@ static const char name_s3c2410[] = "S3C2410";
67static const char name_s3c2412[] = "S3C2412"; 68static const char name_s3c2412[] = "S3C2412";
68static const char name_s3c2440[] = "S3C2440"; 69static const char name_s3c2440[] = "S3C2440";
69static const char name_s3c2442[] = "S3C2442"; 70static const char name_s3c2442[] = "S3C2442";
71static const char name_s3c2443[] = "S3C2443";
70static const char name_s3c2410a[] = "S3C2410A"; 72static const char name_s3c2410a[] = "S3C2410A";
71static const char name_s3c2440a[] = "S3C2440A"; 73static const char name_s3c2440a[] = "S3C2440A";
72 74
@@ -135,6 +137,15 @@ static struct cpu_table cpu_ids[] __initdata = {
135 .name = name_s3c2412, 137 .name = name_s3c2412,
136 }, 138 },
137 { 139 {
140 .idcode = 0x32443001,
141 .idmask = 0xffffffff,
142 .map_io = s3c2443_map_io,
143 .init_clocks = s3c2443_init_clocks,
144 .init_uarts = s3c2443_init_uarts,
145 .init = s3c2443_init,
146 .name = name_s3c2443,
147 },
148 {
138 .idcode = 0x0, /* S3C2400 doesn't have an idcode */ 149 .idcode = 0x0, /* S3C2400 doesn't have an idcode */
139 .idmask = 0xffffffff, 150 .idmask = 0xffffffff,
140 .map_io = s3c2400_map_io, 151 .map_io = s3c2400_map_io,
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/plat-s3c24xx/devs.c
index faccde2092d2..0fe53b39cb2f 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/devs.c 1/* linux/arch/arm/plat-s3c24xx/devs.c
2 * 2 *
3 * Copyright (c) 2004 Simtec Electronics 3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -29,9 +29,10 @@
29#include <asm/irq.h> 29#include <asm/irq.h>
30 30
31#include <asm/arch/regs-serial.h> 31#include <asm/arch/regs-serial.h>
32#include <asm/arch/udc.h>
32 33
33#include "devs.h" 34#include <asm/plat-s3c24xx/devs.h>
34#include "cpu.h" 35#include <asm/plat-s3c24xx/cpu.h>
35 36
36/* Serial port registrations */ 37/* Serial port registrations */
37 38
@@ -230,6 +231,20 @@ struct platform_device s3c_device_usbgadget = {
230 231
231EXPORT_SYMBOL(s3c_device_usbgadget); 232EXPORT_SYMBOL(s3c_device_usbgadget);
232 233
234void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
235{
236 struct s3c2410_udc_mach_info *npd;
237
238 npd = kmalloc(sizeof(*npd), GFP_KERNEL);
239 if (npd) {
240 memcpy(npd, pd, sizeof(*npd));
241 s3c_device_usbgadget.dev.platform_data = npd;
242 } else {
243 printk(KERN_ERR "no memory for udc platform data\n");
244 }
245}
246
247
233/* Watchdog */ 248/* Watchdog */
234 249
235static struct resource s3c_wdt_resource[] = { 250static struct resource s3c_wdt_resource[] = {
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
new file mode 100644
index 000000000000..4540a806f522
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -0,0 +1,1499 @@
1/* linux/arch/arm/plat-s3c24xx/dma.c
2 *
3 * Copyright (c) 2003-2005,2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 DMA core
7 *
8 * http://armlinux.simtec.co.uk/
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15
16#ifdef CONFIG_S3C2410_DMA_DEBUG
17#define DEBUG
18#endif
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/sched.h>
23#include <linux/spinlock.h>
24#include <linux/interrupt.h>
25#include <linux/sysdev.h>
26#include <linux/slab.h>
27#include <linux/errno.h>
28#include <linux/delay.h>
29
30#include <asm/system.h>
31#include <asm/irq.h>
32#include <asm/hardware.h>
33#include <asm/io.h>
34#include <asm/dma.h>
35
36#include <asm/mach/dma.h>
37#include <asm/arch/map.h>
38
39#include <asm/plat-s3c24xx/dma.h>
40
41/* io map for dma */
42static void __iomem *dma_base;
43static struct kmem_cache *dma_kmem;
44
45static int dma_channels;
46
47struct s3c24xx_dma_selection dma_sel;
48
49/* dma channel state information */
50struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
51
52/* debugging functions */
53
54#define BUF_MAGIC (0xcafebabe)
55
56#define dmawarn(fmt...) printk(KERN_DEBUG fmt)
57
58#define dma_regaddr(chan, reg) ((chan)->regs + (reg))
59
60#if 1
61#define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
62#else
63static inline void
64dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
65{
66 pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
67 writel(val, dma_regaddr(chan, reg));
68}
69#endif
70
71#define dma_rdreg(chan, reg) readl((chan)->regs + (reg))
72
73/* captured register state for debug */
74
75struct s3c2410_dma_regstate {
76 unsigned long dcsrc;
77 unsigned long disrc;
78 unsigned long dstat;
79 unsigned long dcon;
80 unsigned long dmsktrig;
81};
82
83#ifdef CONFIG_S3C2410_DMA_DEBUG
84
85/* dmadbg_showregs
86 *
87 * simple debug routine to print the current state of the dma registers
88*/
89
90static void
91dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
92{
93 regs->dcsrc = dma_rdreg(chan, S3C2410_DMA_DCSRC);
94 regs->disrc = dma_rdreg(chan, S3C2410_DMA_DISRC);
95 regs->dstat = dma_rdreg(chan, S3C2410_DMA_DSTAT);
96 regs->dcon = dma_rdreg(chan, S3C2410_DMA_DCON);
97 regs->dmsktrig = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
98}
99
100static void
101dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
102 struct s3c2410_dma_regstate *regs)
103{
104 printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
105 chan->number, fname, line,
106 regs->dcsrc, regs->disrc, regs->dstat, regs->dmsktrig,
107 regs->dcon);
108}
109
110static void
111dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
112{
113 struct s3c2410_dma_regstate state;
114
115 dmadbg_capture(chan, &state);
116
117 printk(KERN_DEBUG "dma%d: %s:%d: ls=%d, cur=%p, %p %p\n",
118 chan->number, fname, line, chan->load_state,
119 chan->curr, chan->next, chan->end);
120
121 dmadbg_dumpregs(fname, line, chan, &state);
122}
123
124static void
125dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
126{
127 struct s3c2410_dma_regstate state;
128
129 dmadbg_capture(chan, &state);
130 dmadbg_dumpregs(fname, line, chan, &state);
131}
132
133#define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
134#define dbg_showchan(chan) dmadbg_showchan(__FUNCTION__, __LINE__, (chan))
135#else
136#define dbg_showregs(chan) do { } while(0)
137#define dbg_showchan(chan) do { } while(0)
138#endif /* CONFIG_S3C2410_DMA_DEBUG */
139
140static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
141
142/* lookup_dma_channel
143 *
144 * change the dma channel number given into a real dma channel id
145*/
146
147static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
148{
149 if (channel & DMACH_LOW_LEVEL)
150 return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
151 else
152 return dma_chan_map[channel];
153}
154
155/* s3c2410_dma_stats_timeout
156 *
157 * Update DMA stats from timeout info
158*/
159
160static void
161s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
162{
163 if (stats == NULL)
164 return;
165
166 if (val > stats->timeout_longest)
167 stats->timeout_longest = val;
168 if (val < stats->timeout_shortest)
169 stats->timeout_shortest = val;
170
171 stats->timeout_avg += val;
172}
173
174/* s3c2410_dma_waitforload
175 *
176 * wait for the DMA engine to load a buffer, and update the state accordingly
177*/
178
179static int
180s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
181{
182 int timeout = chan->load_timeout;
183 int took;
184
185 if (chan->load_state != S3C2410_DMALOAD_1LOADED) {
186 printk(KERN_ERR "dma%d: s3c2410_dma_waitforload() called in loadstate %d from line %d\n", chan->number, chan->load_state, line);
187 return 0;
188 }
189
190 if (chan->stats != NULL)
191 chan->stats->loads++;
192
193 while (--timeout > 0) {
194 if ((dma_rdreg(chan, S3C2410_DMA_DSTAT) << (32-20)) != 0) {
195 took = chan->load_timeout - timeout;
196
197 s3c2410_dma_stats_timeout(chan->stats, took);
198
199 switch (chan->load_state) {
200 case S3C2410_DMALOAD_1LOADED:
201 chan->load_state = S3C2410_DMALOAD_1RUNNING;
202 break;
203
204 default:
205 printk(KERN_ERR "dma%d: unknown load_state in s3c2410_dma_waitforload() %d\n", chan->number, chan->load_state);
206 }
207
208 return 1;
209 }
210 }
211
212 if (chan->stats != NULL) {
213 chan->stats->timeout_failed++;
214 }
215
216 return 0;
217}
218
219
220
221/* s3c2410_dma_loadbuffer
222 *
223 * load a buffer, and update the channel state
224*/
225
226static inline int
227s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
228 struct s3c2410_dma_buf *buf)
229{
230 unsigned long reload;
231
232 pr_debug("s3c2410_chan_loadbuffer: loading buff %p (0x%08lx,0x%06x)\n",
233 buf, (unsigned long)buf->data, buf->size);
234
235 if (buf == NULL) {
236 dmawarn("buffer is NULL\n");
237 return -EINVAL;
238 }
239
240 /* check the state of the channel before we do anything */
241
242 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
243 dmawarn("load_state is S3C2410_DMALOAD_1LOADED\n");
244 }
245
246 if (chan->load_state == S3C2410_DMALOAD_1LOADED_1RUNNING) {
247 dmawarn("state is S3C2410_DMALOAD_1LOADED_1RUNNING\n");
248 }
249
250 /* it would seem sensible if we are the last buffer to not bother
251 * with the auto-reload bit, so that the DMA engine will not try
252 * and load another transfer after this one has finished...
253 */
254 if (chan->load_state == S3C2410_DMALOAD_NONE) {
255 pr_debug("load_state is none, checking for noreload (next=%p)\n",
256 buf->next);
257 reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
258 } else {
259 //pr_debug("load_state is %d => autoreload\n", chan->load_state);
260 reload = S3C2410_DCON_AUTORELOAD;
261 }
262
263 if ((buf->data & 0xf0000000) != 0x30000000) {
264 dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
265 }
266
267 writel(buf->data, chan->addr_reg);
268
269 dma_wrreg(chan, S3C2410_DMA_DCON,
270 chan->dcon | reload | (buf->size/chan->xfer_unit));
271
272 chan->next = buf->next;
273
274 /* update the state of the channel */
275
276 switch (chan->load_state) {
277 case S3C2410_DMALOAD_NONE:
278 chan->load_state = S3C2410_DMALOAD_1LOADED;
279 break;
280
281 case S3C2410_DMALOAD_1RUNNING:
282 chan->load_state = S3C2410_DMALOAD_1LOADED_1RUNNING;
283 break;
284
285 default:
286 dmawarn("dmaload: unknown state %d in loadbuffer\n",
287 chan->load_state);
288 break;
289 }
290
291 return 0;
292}
293
294/* s3c2410_dma_call_op
295 *
296 * small routine to call the op routine with the given op if it has been
297 * registered
298*/
299
300static void
301s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
302{
303 if (chan->op_fn != NULL) {
304 (chan->op_fn)(chan, op);
305 }
306}
307
308/* s3c2410_dma_buffdone
309 *
310 * small wrapper to check if callback routine needs to be called, and
311 * if so, call it
312*/
313
314static inline void
315s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
316 enum s3c2410_dma_buffresult result)
317{
318#if 0
319 pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
320 chan->callback_fn, buf, buf->id, buf->size, result);
321#endif
322
323 if (chan->callback_fn != NULL) {
324 (chan->callback_fn)(chan, buf->id, buf->size, result);
325 }
326}
327
328/* s3c2410_dma_start
329 *
330 * start a dma channel going
331*/
332
333static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
334{
335 unsigned long tmp;
336 unsigned long flags;
337
338 pr_debug("s3c2410_start_dma: channel=%d\n", chan->number);
339
340 local_irq_save(flags);
341
342 if (chan->state == S3C2410_DMA_RUNNING) {
343 pr_debug("s3c2410_start_dma: already running (%d)\n", chan->state);
344 local_irq_restore(flags);
345 return 0;
346 }
347
348 chan->state = S3C2410_DMA_RUNNING;
349
350 /* check wether there is anything to load, and if not, see
351 * if we can find anything to load
352 */
353
354 if (chan->load_state == S3C2410_DMALOAD_NONE) {
355 if (chan->next == NULL) {
356 printk(KERN_ERR "dma%d: channel has nothing loaded\n",
357 chan->number);
358 chan->state = S3C2410_DMA_IDLE;
359 local_irq_restore(flags);
360 return -EINVAL;
361 }
362
363 s3c2410_dma_loadbuffer(chan, chan->next);
364 }
365
366 dbg_showchan(chan);
367
368 /* enable the channel */
369
370 if (!chan->irq_enabled) {
371 enable_irq(chan->irq);
372 chan->irq_enabled = 1;
373 }
374
375 /* start the channel going */
376
377 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
378 tmp &= ~S3C2410_DMASKTRIG_STOP;
379 tmp |= S3C2410_DMASKTRIG_ON;
380 dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
381
382 pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
383
384#if 0
385 /* the dma buffer loads should take care of clearing the AUTO
386 * reloading feature */
387 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
388 tmp &= ~S3C2410_DCON_NORELOAD;
389 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
390#endif
391
392 s3c2410_dma_call_op(chan, S3C2410_DMAOP_START);
393
394 dbg_showchan(chan);
395
396 /* if we've only loaded one buffer onto the channel, then chec
397 * to see if we have another, and if so, try and load it so when
398 * the first buffer is finished, the new one will be loaded onto
399 * the channel */
400
401 if (chan->next != NULL) {
402 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
403
404 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
405 pr_debug("%s: buff not yet loaded, no more todo\n",
406 __FUNCTION__);
407 } else {
408 chan->load_state = S3C2410_DMALOAD_1RUNNING;
409 s3c2410_dma_loadbuffer(chan, chan->next);
410 }
411
412 } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
413 s3c2410_dma_loadbuffer(chan, chan->next);
414 }
415 }
416
417
418 local_irq_restore(flags);
419
420 return 0;
421}
422
423/* s3c2410_dma_canload
424 *
425 * work out if we can queue another buffer into the DMA engine
426*/
427
428static int
429s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
430{
431 if (chan->load_state == S3C2410_DMALOAD_NONE ||
432 chan->load_state == S3C2410_DMALOAD_1RUNNING)
433 return 1;
434
435 return 0;
436}
437
438/* s3c2410_dma_enqueue
439 *
440 * queue an given buffer for dma transfer.
441 *
442 * id the device driver's id information for this buffer
443 * data the physical address of the buffer data
444 * size the size of the buffer in bytes
445 *
446 * If the channel is not running, then the flag S3C2410_DMAF_AUTOSTART
447 * is checked, and if set, the channel is started. If this flag isn't set,
448 * then an error will be returned.
449 *
450 * It is possible to queue more than one DMA buffer onto a channel at
451 * once, and the code will deal with the re-loading of the next buffer
452 * when necessary.
453*/
454
455int s3c2410_dma_enqueue(unsigned int channel, void *id,
456 dma_addr_t data, int size)
457{
458 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
459 struct s3c2410_dma_buf *buf;
460 unsigned long flags;
461
462 if (chan == NULL)
463 return -EINVAL;
464
465 pr_debug("%s: id=%p, data=%08x, size=%d\n",
466 __FUNCTION__, id, (unsigned int)data, size);
467
468 buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
469 if (buf == NULL) {
470 pr_debug("%s: out of memory (%ld alloc)\n",
471 __FUNCTION__, (long)sizeof(*buf));
472 return -ENOMEM;
473 }
474
475 //pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
476 //dbg_showchan(chan);
477
478 buf->next = NULL;
479 buf->data = buf->ptr = data;
480 buf->size = size;
481 buf->id = id;
482 buf->magic = BUF_MAGIC;
483
484 local_irq_save(flags);
485
486 if (chan->curr == NULL) {
487 /* we've got nothing loaded... */
488 pr_debug("%s: buffer %p queued onto empty channel\n",
489 __FUNCTION__, buf);
490
491 chan->curr = buf;
492 chan->end = buf;
493 chan->next = NULL;
494 } else {
495 pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
496 chan->number, __FUNCTION__, buf);
497
498 if (chan->end == NULL)
499 pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
500 chan->number, __FUNCTION__, chan);
501
502 chan->end->next = buf;
503 chan->end = buf;
504 }
505
506 /* if necessary, update the next buffer field */
507 if (chan->next == NULL)
508 chan->next = buf;
509
510 /* check to see if we can load a buffer */
511 if (chan->state == S3C2410_DMA_RUNNING) {
512 if (chan->load_state == S3C2410_DMALOAD_1LOADED && 1) {
513 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
514 printk(KERN_ERR "dma%d: loadbuffer:"
515 "timeout loading buffer\n",
516 chan->number);
517 dbg_showchan(chan);
518 local_irq_restore(flags);
519 return -EINVAL;
520 }
521 }
522
523 while (s3c2410_dma_canload(chan) && chan->next != NULL) {
524 s3c2410_dma_loadbuffer(chan, chan->next);
525 }
526 } else if (chan->state == S3C2410_DMA_IDLE) {
527 if (chan->flags & S3C2410_DMAF_AUTOSTART) {
528 s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_START);
529 }
530 }
531
532 local_irq_restore(flags);
533 return 0;
534}
535
536EXPORT_SYMBOL(s3c2410_dma_enqueue);
537
538static inline void
539s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
540{
541 int magicok = (buf->magic == BUF_MAGIC);
542
543 buf->magic = -1;
544
545 if (magicok) {
546 kmem_cache_free(dma_kmem, buf);
547 } else {
548 printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
549 }
550}
551
552/* s3c2410_dma_lastxfer
553 *
554 * called when the system is out of buffers, to ensure that the channel
555 * is prepared for shutdown.
556*/
557
558static inline void
559s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
560{
561#if 0
562 pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
563 chan->number, chan->load_state);
564#endif
565
566 switch (chan->load_state) {
567 case S3C2410_DMALOAD_NONE:
568 break;
569
570 case S3C2410_DMALOAD_1LOADED:
571 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
572 /* flag error? */
573 printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
574 chan->number, __FUNCTION__);
575 return;
576 }
577 break;
578
579 case S3C2410_DMALOAD_1LOADED_1RUNNING:
580 /* I belive in this case we do not have anything to do
581 * until the next buffer comes along, and we turn off the
582 * reload */
583 return;
584
585 default:
586 pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
587 chan->number, chan->load_state);
588 return;
589
590 }
591
592 /* hopefully this'll shut the damned thing up after the transfer... */
593 dma_wrreg(chan, S3C2410_DMA_DCON, chan->dcon | S3C2410_DCON_NORELOAD);
594}
595
596
597#define dmadbg2(x...)
598
599static irqreturn_t
600s3c2410_dma_irq(int irq, void *devpw)
601{
602 struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
603 struct s3c2410_dma_buf *buf;
604
605 buf = chan->curr;
606
607 dbg_showchan(chan);
608
609 /* modify the channel state */
610
611 switch (chan->load_state) {
612 case S3C2410_DMALOAD_1RUNNING:
613 /* TODO - if we are running only one buffer, we probably
614 * want to reload here, and then worry about the buffer
615 * callback */
616
617 chan->load_state = S3C2410_DMALOAD_NONE;
618 break;
619
620 case S3C2410_DMALOAD_1LOADED:
621 /* iirc, we should go back to NONE loaded here, we
622 * had a buffer, and it was never verified as being
623 * loaded.
624 */
625
626 chan->load_state = S3C2410_DMALOAD_NONE;
627 break;
628
629 case S3C2410_DMALOAD_1LOADED_1RUNNING:
630 /* we'll worry about checking to see if another buffer is
631 * ready after we've called back the owner. This should
632 * ensure we do not wait around too long for the DMA
633 * engine to start the next transfer
634 */
635
636 chan->load_state = S3C2410_DMALOAD_1LOADED;
637 break;
638
639 case S3C2410_DMALOAD_NONE:
640 printk(KERN_ERR "dma%d: IRQ with no loaded buffer?\n",
641 chan->number);
642 break;
643
644 default:
645 printk(KERN_ERR "dma%d: IRQ in invalid load_state %d\n",
646 chan->number, chan->load_state);
647 break;
648 }
649
650 if (buf != NULL) {
651 /* update the chain to make sure that if we load any more
652 * buffers when we call the callback function, things should
653 * work properly */
654
655 chan->curr = buf->next;
656 buf->next = NULL;
657
658 if (buf->magic != BUF_MAGIC) {
659 printk(KERN_ERR "dma%d: %s: buf %p incorrect magic\n",
660 chan->number, __FUNCTION__, buf);
661 return IRQ_HANDLED;
662 }
663
664 s3c2410_dma_buffdone(chan, buf, S3C2410_RES_OK);
665
666 /* free resouces */
667 s3c2410_dma_freebuf(buf);
668 } else {
669 }
670
671 /* only reload if the channel is still running... our buffer done
672 * routine may have altered the state by requesting the dma channel
673 * to stop or shutdown... */
674
675 /* todo: check that when the channel is shut-down from inside this
676 * function, we cope with unsetting reload, etc */
677
678 if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
679 unsigned long flags;
680
681 switch (chan->load_state) {
682 case S3C2410_DMALOAD_1RUNNING:
683 /* don't need to do anything for this state */
684 break;
685
686 case S3C2410_DMALOAD_NONE:
687 /* can load buffer immediately */
688 break;
689
690 case S3C2410_DMALOAD_1LOADED:
691 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
692 /* flag error? */
693 printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
694 chan->number, __FUNCTION__);
695 return IRQ_HANDLED;
696 }
697
698 break;
699
700 case S3C2410_DMALOAD_1LOADED_1RUNNING:
701 goto no_load;
702
703 default:
704 printk(KERN_ERR "dma%d: unknown load_state in irq, %d\n",
705 chan->number, chan->load_state);
706 return IRQ_HANDLED;
707 }
708
709 local_irq_save(flags);
710 s3c2410_dma_loadbuffer(chan, chan->next);
711 local_irq_restore(flags);
712 } else {
713 s3c2410_dma_lastxfer(chan);
714
715 /* see if we can stop this channel.. */
716 if (chan->load_state == S3C2410_DMALOAD_NONE) {
717 pr_debug("dma%d: end of transfer, stopping channel (%ld)\n",
718 chan->number, jiffies);
719 s3c2410_dma_ctrl(chan->number | DMACH_LOW_LEVEL,
720 S3C2410_DMAOP_STOP);
721 }
722 }
723
724 no_load:
725 return IRQ_HANDLED;
726}
727
728static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel);
729
730/* s3c2410_request_dma
731 *
732 * get control of an dma channel
733*/
734
735int s3c2410_dma_request(unsigned int channel,
736 struct s3c2410_dma_client *client,
737 void *dev)
738{
739 struct s3c2410_dma_chan *chan;
740 unsigned long flags;
741 int err;
742
743 pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
744 channel, client->name, dev);
745
746 local_irq_save(flags);
747
748 chan = s3c2410_dma_map_channel(channel);
749 if (chan == NULL) {
750 local_irq_restore(flags);
751 return -EBUSY;
752 }
753
754 dbg_showchan(chan);
755
756 chan->client = client;
757 chan->in_use = 1;
758
759 if (!chan->irq_claimed) {
760 pr_debug("dma%d: %s : requesting irq %d\n",
761 channel, __FUNCTION__, chan->irq);
762
763 chan->irq_claimed = 1;
764 local_irq_restore(flags);
765
766 err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
767 client->name, (void *)chan);
768
769 local_irq_save(flags);
770
771 if (err) {
772 chan->in_use = 0;
773 chan->irq_claimed = 0;
774 local_irq_restore(flags);
775
776 printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
777 client->name, chan->irq, chan->number);
778 return err;
779 }
780
781 chan->irq_enabled = 1;
782 }
783
784 local_irq_restore(flags);
785
786 /* need to setup */
787
788 pr_debug("%s: channel initialised, %p\n", __FUNCTION__, chan);
789
790 return 0;
791}
792
793EXPORT_SYMBOL(s3c2410_dma_request);
794
795/* s3c2410_dma_free
796 *
797 * release the given channel back to the system, will stop and flush
798 * any outstanding transfers, and ensure the channel is ready for the
799 * next claimant.
800 *
801 * Note, although a warning is currently printed if the freeing client
802 * info is not the same as the registrant's client info, the free is still
803 * allowed to go through.
804*/
805
806int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
807{
808 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
809 unsigned long flags;
810
811 if (chan == NULL)
812 return -EINVAL;
813
814 local_irq_save(flags);
815
816 if (chan->client != client) {
817 printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
818 channel, chan->client, client);
819 }
820
821 /* sort out stopping and freeing the channel */
822
823 if (chan->state != S3C2410_DMA_IDLE) {
824 pr_debug("%s: need to stop dma channel %p\n",
825 __FUNCTION__, chan);
826
827 /* possibly flush the channel */
828 s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STOP);
829 }
830
831 chan->client = NULL;
832 chan->in_use = 0;
833
834 if (chan->irq_claimed)
835 free_irq(chan->irq, (void *)chan);
836
837 chan->irq_claimed = 0;
838
839 if (!(channel & DMACH_LOW_LEVEL))
840 dma_chan_map[channel] = NULL;
841
842 local_irq_restore(flags);
843
844 return 0;
845}
846
847EXPORT_SYMBOL(s3c2410_dma_free);
848
849static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
850{
851 unsigned long flags;
852 unsigned long tmp;
853
854 pr_debug("%s:\n", __FUNCTION__);
855
856 dbg_showchan(chan);
857
858 local_irq_save(flags);
859
860 s3c2410_dma_call_op(chan, S3C2410_DMAOP_STOP);
861
862 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
863 tmp |= S3C2410_DMASKTRIG_STOP;
864 //tmp &= ~S3C2410_DMASKTRIG_ON;
865 dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
866
867#if 0
868 /* should also clear interrupts, according to WinCE BSP */
869 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
870 tmp |= S3C2410_DCON_NORELOAD;
871 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
872#endif
873
874 /* should stop do this, or should we wait for flush? */
875 chan->state = S3C2410_DMA_IDLE;
876 chan->load_state = S3C2410_DMALOAD_NONE;
877
878 local_irq_restore(flags);
879
880 return 0;
881}
882
883void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
884{
885 unsigned long tmp;
886 unsigned int timeout = 0x10000;
887
888 while (timeout-- > 0) {
889 tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
890
891 if (!(tmp & S3C2410_DMASKTRIG_ON))
892 return;
893 }
894
895 pr_debug("dma%d: failed to stop?\n", chan->number);
896}
897
898
899/* s3c2410_dma_flush
900 *
901 * stop the channel, and remove all current and pending transfers
902*/
903
904static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
905{
906 struct s3c2410_dma_buf *buf, *next;
907 unsigned long flags;
908
909 pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
910
911 dbg_showchan(chan);
912
913 local_irq_save(flags);
914
915 if (chan->state != S3C2410_DMA_IDLE) {
916 pr_debug("%s: stopping channel...\n", __FUNCTION__ );
917 s3c2410_dma_ctrl(chan->number, S3C2410_DMAOP_STOP);
918 }
919
920 buf = chan->curr;
921 if (buf == NULL)
922 buf = chan->next;
923
924 chan->curr = chan->next = chan->end = NULL;
925
926 if (buf != NULL) {
927 for ( ; buf != NULL; buf = next) {
928 next = buf->next;
929
930 pr_debug("%s: free buffer %p, next %p\n",
931 __FUNCTION__, buf, buf->next);
932
933 s3c2410_dma_buffdone(chan, buf, S3C2410_RES_ABORT);
934 s3c2410_dma_freebuf(buf);
935 }
936 }
937
938 dbg_showregs(chan);
939
940 s3c2410_dma_waitforstop(chan);
941
942#if 0
943 /* should also clear interrupts, according to WinCE BSP */
944 {
945 unsigned long tmp;
946
947 tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
948 tmp |= S3C2410_DCON_NORELOAD;
949 dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
950 }
951#endif
952
953 dbg_showregs(chan);
954
955 local_irq_restore(flags);
956
957 return 0;
958}
959
960int
961s3c2410_dma_started(struct s3c2410_dma_chan *chan)
962{
963 unsigned long flags;
964
965 local_irq_save(flags);
966
967 dbg_showchan(chan);
968
969 /* if we've only loaded one buffer onto the channel, then chec
970 * to see if we have another, and if so, try and load it so when
971 * the first buffer is finished, the new one will be loaded onto
972 * the channel */
973
974 if (chan->next != NULL) {
975 if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
976
977 if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
978 pr_debug("%s: buff not yet loaded, no more todo\n",
979 __FUNCTION__);
980 } else {
981 chan->load_state = S3C2410_DMALOAD_1RUNNING;
982 s3c2410_dma_loadbuffer(chan, chan->next);
983 }
984
985 } else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
986 s3c2410_dma_loadbuffer(chan, chan->next);
987 }
988 }
989
990
991 local_irq_restore(flags);
992
993 return 0;
994
995}
996
997int
998s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
999{
1000 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1001
1002 if (chan == NULL)
1003 return -EINVAL;
1004
1005 switch (op) {
1006 case S3C2410_DMAOP_START:
1007 return s3c2410_dma_start(chan);
1008
1009 case S3C2410_DMAOP_STOP:
1010 return s3c2410_dma_dostop(chan);
1011
1012 case S3C2410_DMAOP_PAUSE:
1013 case S3C2410_DMAOP_RESUME:
1014 return -ENOENT;
1015
1016 case S3C2410_DMAOP_FLUSH:
1017 return s3c2410_dma_flush(chan);
1018
1019 case S3C2410_DMAOP_STARTED:
1020 return s3c2410_dma_started(chan);
1021
1022 case S3C2410_DMAOP_TIMEOUT:
1023 return 0;
1024
1025 }
1026
1027 return -ENOENT; /* unknown, don't bother */
1028}
1029
1030EXPORT_SYMBOL(s3c2410_dma_ctrl);
1031
1032/* DMA configuration for each channel
1033 *
1034 * DISRCC -> source of the DMA (AHB,APB)
1035 * DISRC -> source address of the DMA
1036 * DIDSTC -> destination of the DMA (AHB,APD)
1037 * DIDST -> destination address of the DMA
1038*/
1039
1040/* s3c2410_dma_config
1041 *
1042 * xfersize: size of unit in bytes (1,2,4)
1043 * dcon: base value of the DCONx register
1044*/
1045
1046int s3c2410_dma_config(dmach_t channel,
1047 int xferunit,
1048 int dcon)
1049{
1050 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1051
1052 pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
1053 __FUNCTION__, channel, xferunit, dcon);
1054
1055 if (chan == NULL)
1056 return -EINVAL;
1057
1058 pr_debug("%s: Initial dcon is %08x\n", __FUNCTION__, dcon);
1059
1060 dcon |= chan->dcon & dma_sel.dcon_mask;
1061
1062 pr_debug("%s: New dcon is %08x\n", __FUNCTION__, dcon);
1063
1064 switch (xferunit) {
1065 case 1:
1066 dcon |= S3C2410_DCON_BYTE;
1067 break;
1068
1069 case 2:
1070 dcon |= S3C2410_DCON_HALFWORD;
1071 break;
1072
1073 case 4:
1074 dcon |= S3C2410_DCON_WORD;
1075 break;
1076
1077 default:
1078 pr_debug("%s: bad transfer size %d\n", __FUNCTION__, xferunit);
1079 return -EINVAL;
1080 }
1081
1082 dcon |= S3C2410_DCON_HWTRIG;
1083 dcon |= S3C2410_DCON_INTREQ;
1084
1085 pr_debug("%s: dcon now %08x\n", __FUNCTION__, dcon);
1086
1087 chan->dcon = dcon;
1088 chan->xfer_unit = xferunit;
1089
1090 return 0;
1091}
1092
1093EXPORT_SYMBOL(s3c2410_dma_config);
1094
1095int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
1096{
1097 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1098
1099 if (chan == NULL)
1100 return -EINVAL;
1101
1102 pr_debug("%s: chan=%p, flags=%08x\n", __FUNCTION__, chan, flags);
1103
1104 chan->flags = flags;
1105
1106 return 0;
1107}
1108
1109EXPORT_SYMBOL(s3c2410_dma_setflags);
1110
1111
1112/* do we need to protect the settings of the fields from
1113 * irq?
1114*/
1115
1116int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
1117{
1118 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1119
1120 if (chan == NULL)
1121 return -EINVAL;
1122
1123 pr_debug("%s: chan=%p, op rtn=%p\n", __FUNCTION__, chan, rtn);
1124
1125 chan->op_fn = rtn;
1126
1127 return 0;
1128}
1129
1130EXPORT_SYMBOL(s3c2410_dma_set_opfn);
1131
1132int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
1133{
1134 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1135
1136 if (chan == NULL)
1137 return -EINVAL;
1138
1139 pr_debug("%s: chan=%p, callback rtn=%p\n", __FUNCTION__, chan, rtn);
1140
1141 chan->callback_fn = rtn;
1142
1143 return 0;
1144}
1145
1146EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
1147
1148/* s3c2410_dma_devconfig
1149 *
1150 * configure the dma source/destination hardware type and address
1151 *
1152 * source: S3C2410_DMASRC_HW: source is hardware
1153 * S3C2410_DMASRC_MEM: source is memory
1154 *
1155 * hwcfg: the value for xxxSTCn register,
1156 * bit 0: 0=increment pointer, 1=leave pointer
1157 * bit 1: 0=soucre is AHB, 1=soucre is APB
1158 *
1159 * devaddr: physical address of the source
1160*/
1161
1162int s3c2410_dma_devconfig(int channel,
1163 enum s3c2410_dmasrc source,
1164 int hwcfg,
1165 unsigned long devaddr)
1166{
1167 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1168
1169 if (chan == NULL)
1170 return -EINVAL;
1171
1172 pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
1173 __FUNCTION__, (int)source, hwcfg, devaddr);
1174
1175 chan->source = source;
1176 chan->dev_addr = devaddr;
1177
1178 switch (source) {
1179 case S3C2410_DMASRC_HW:
1180 /* source is hardware */
1181 pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
1182 __FUNCTION__, devaddr, hwcfg);
1183 dma_wrreg(chan, S3C2410_DMA_DISRCC, hwcfg & 3);
1184 dma_wrreg(chan, S3C2410_DMA_DISRC, devaddr);
1185 dma_wrreg(chan, S3C2410_DMA_DIDSTC, (0<<1) | (0<<0));
1186
1187 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
1188 return 0;
1189
1190 case S3C2410_DMASRC_MEM:
1191 /* source is memory */
1192 pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d\n",
1193 __FUNCTION__, devaddr, hwcfg);
1194 dma_wrreg(chan, S3C2410_DMA_DISRCC, (0<<1) | (0<<0));
1195 dma_wrreg(chan, S3C2410_DMA_DIDST, devaddr);
1196 dma_wrreg(chan, S3C2410_DMA_DIDSTC, hwcfg & 3);
1197
1198 chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DISRC);
1199 return 0;
1200 }
1201
1202 printk(KERN_ERR "dma%d: invalid source type (%d)\n", channel, source);
1203 return -EINVAL;
1204}
1205
1206EXPORT_SYMBOL(s3c2410_dma_devconfig);
1207
1208/* s3c2410_dma_getposition
1209 *
1210 * returns the current transfer points for the dma source and destination
1211*/
1212
1213int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
1214{
1215 struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
1216
1217 if (chan == NULL)
1218 return -EINVAL;
1219
1220 if (src != NULL)
1221 *src = dma_rdreg(chan, S3C2410_DMA_DCSRC);
1222
1223 if (dst != NULL)
1224 *dst = dma_rdreg(chan, S3C2410_DMA_DCDST);
1225
1226 return 0;
1227}
1228
1229EXPORT_SYMBOL(s3c2410_dma_getposition);
1230
1231
1232/* system device class */
1233
1234#ifdef CONFIG_PM
1235
1236static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
1237{
1238 struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
1239
1240 printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
1241
1242 if (dma_rdreg(cp, S3C2410_DMA_DMASKTRIG) & S3C2410_DMASKTRIG_ON) {
1243 /* the dma channel is still working, which is probably
1244 * a bad thing to do over suspend/resume. We stop the
1245 * channel and assume that the client is either going to
1246 * retry after resume, or that it is broken.
1247 */
1248
1249 printk(KERN_INFO "dma: stopping channel %d due to suspend\n",
1250 cp->number);
1251
1252 s3c2410_dma_dostop(cp);
1253 }
1254
1255 return 0;
1256}
1257
1258static int s3c2410_dma_resume(struct sys_device *dev)
1259{
1260 return 0;
1261}
1262
1263#else
1264#define s3c2410_dma_suspend NULL
1265#define s3c2410_dma_resume NULL
1266#endif /* CONFIG_PM */
1267
1268struct sysdev_class dma_sysclass = {
1269 set_kset_name("s3c24xx-dma"),
1270 .suspend = s3c2410_dma_suspend,
1271 .resume = s3c2410_dma_resume,
1272};
1273
1274/* kmem cache implementation */
1275
1276static void s3c2410_dma_cache_ctor(void *p, struct kmem_cache *c, unsigned long f)
1277{
1278 memset(p, 0, sizeof(struct s3c2410_dma_buf));
1279}
1280
1281/* initialisation code */
1282
1283int __init s3c24xx_dma_sysclass_init(void)
1284{
1285 int ret = sysdev_class_register(&dma_sysclass);
1286
1287 if (ret != 0)
1288 printk(KERN_ERR "dma sysclass registration failed\n");
1289
1290 return ret;
1291}
1292
1293core_initcall(s3c24xx_dma_sysclass_init);
1294
1295int __init s3c24xx_dma_sysdev_register(void)
1296{
1297 struct s3c2410_dma_chan *cp = s3c2410_chans;
1298 int channel, ret;
1299
1300 for (channel = 0; channel < dma_channels; cp++, channel++) {
1301 cp->dev.cls = &dma_sysclass;
1302 cp->dev.id = channel;
1303 ret = sysdev_register(&cp->dev);
1304
1305 if (ret) {
1306 printk(KERN_ERR "error registering dev for dma %d\n",
1307 channel);
1308 return ret;
1309 }
1310 }
1311
1312 return 0;
1313}
1314
1315late_initcall(s3c24xx_dma_sysdev_register);
1316
1317int __init s3c24xx_dma_init(unsigned int channels, unsigned int irq,
1318 unsigned int stride)
1319{
1320 struct s3c2410_dma_chan *cp;
1321 int channel;
1322 int ret;
1323
1324 printk("S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics\n");
1325
1326 dma_channels = channels;
1327
1328 dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);
1329 if (dma_base == NULL) {
1330 printk(KERN_ERR "dma failed to remap register block\n");
1331 return -ENOMEM;
1332 }
1333
1334 dma_kmem = kmem_cache_create("dma_desc",
1335 sizeof(struct s3c2410_dma_buf), 0,
1336 SLAB_HWCACHE_ALIGN,
1337 s3c2410_dma_cache_ctor, NULL);
1338
1339 if (dma_kmem == NULL) {
1340 printk(KERN_ERR "dma failed to make kmem cache\n");
1341 ret = -ENOMEM;
1342 goto err;
1343 }
1344
1345 for (channel = 0; channel < channels; channel++) {
1346 cp = &s3c2410_chans[channel];
1347
1348 memset(cp, 0, sizeof(struct s3c2410_dma_chan));
1349
1350 /* dma channel irqs are in order.. */
1351 cp->number = channel;
1352 cp->irq = channel + irq;
1353 cp->regs = dma_base + (channel * stride);
1354
1355 /* point current stats somewhere */
1356 cp->stats = &cp->stats_store;
1357 cp->stats_store.timeout_shortest = LONG_MAX;
1358
1359 /* basic channel configuration */
1360
1361 cp->load_timeout = 1<<18;
1362
1363 printk("DMA channel %d at %p, irq %d\n",
1364 cp->number, cp->regs, cp->irq);
1365 }
1366
1367 return 0;
1368
1369 err:
1370 kmem_cache_destroy(dma_kmem);
1371 iounmap(dma_base);
1372 dma_base = NULL;
1373 return ret;
1374}
1375
1376int s3c2410_dma_init(void)
1377{
1378 return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
1379}
1380
1381static inline int is_channel_valid(unsigned int channel)
1382{
1383 return (channel & DMA_CH_VALID);
1384}
1385
1386static struct s3c24xx_dma_order *dma_order;
1387
1388
1389/* s3c2410_dma_map_channel()
1390 *
1391 * turn the virtual channel number into a real, and un-used hardware
1392 * channel.
1393 *
1394 * first, try the dma ordering given to us by either the relevant
1395 * dma code, or the board. Then just find the first usable free
1396 * channel
1397*/
1398
1399struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)
1400{
1401 struct s3c24xx_dma_order_ch *ord = NULL;
1402 struct s3c24xx_dma_map *ch_map;
1403 struct s3c2410_dma_chan *dmach;
1404 int ch;
1405
1406 if (dma_sel.map == NULL || channel > dma_sel.map_size)
1407 return NULL;
1408
1409 ch_map = dma_sel.map + channel;
1410
1411 /* first, try the board mapping */
1412
1413 if (dma_order) {
1414 ord = &dma_order->channels[channel];
1415
1416 for (ch = 0; ch < dma_channels; ch++) {
1417 if (!is_channel_valid(ord->list[ch]))
1418 continue;
1419
1420 if (s3c2410_chans[ord->list[ch]].in_use == 0) {
1421 ch = ord->list[ch] & ~DMA_CH_VALID;
1422 goto found;
1423 }
1424 }
1425
1426 if (ord->flags & DMA_CH_NEVER)
1427 return NULL;
1428 }
1429
1430 /* second, search the channel map for first free */
1431
1432 for (ch = 0; ch < dma_channels; ch++) {
1433 if (!is_channel_valid(ch_map->channels[ch]))
1434 continue;
1435
1436 if (s3c2410_chans[ch].in_use == 0) {
1437 printk("mapped channel %d to %d\n", channel, ch);
1438 break;
1439 }
1440 }
1441
1442 if (ch >= dma_channels)
1443 return NULL;
1444
1445 /* update our channel mapping */
1446
1447 found:
1448 dmach = &s3c2410_chans[ch];
1449 dma_chan_map[channel] = dmach;
1450
1451 /* select the channel */
1452
1453 (dma_sel.select)(dmach, ch_map);
1454
1455 return dmach;
1456}
1457
1458static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch)
1459{
1460 return 0;
1461}
1462
1463int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)
1464{
1465 struct s3c24xx_dma_map *nmap;
1466 size_t map_sz = sizeof(*nmap) * sel->map_size;
1467 int ptr;
1468
1469 nmap = kmalloc(map_sz, GFP_KERNEL);
1470 if (nmap == NULL)
1471 return -ENOMEM;
1472
1473 memcpy(nmap, sel->map, map_sz);
1474 memcpy(&dma_sel, sel, sizeof(*sel));
1475
1476 dma_sel.map = nmap;
1477
1478 for (ptr = 0; ptr < sel->map_size; ptr++)
1479 s3c24xx_dma_check_entry(nmap+ptr, ptr);
1480
1481 return 0;
1482}
1483
1484int __init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)
1485{
1486 struct s3c24xx_dma_order *nord = dma_order;
1487
1488 if (nord == NULL)
1489 nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);
1490
1491 if (nord == NULL) {
1492 printk(KERN_ERR "no memory to store dma channel order\n");
1493 return -ENOMEM;
1494 }
1495
1496 dma_order = nord;
1497 memcpy(nord, ord, sizeof(struct s3c24xx_dma_order));
1498 return 0;
1499}
diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c
new file mode 100644
index 000000000000..ec3a09c4d181
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/gpio.c
@@ -0,0 +1,188 @@
1/* linux/arch/arm/plat-s3c24xx/gpio.c
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C24XX GPIO support
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23
24#include <linux/kernel.h>
25#include <linux/init.h>
26#include <linux/module.h>
27#include <linux/interrupt.h>
28#include <linux/ioport.h>
29
30#include <asm/hardware.h>
31#include <asm/irq.h>
32#include <asm/io.h>
33
34#include <asm/arch/regs-gpio.h>
35
36void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
37{
38 void __iomem *base = S3C24XX_GPIO_BASE(pin);
39 unsigned long mask;
40 unsigned long con;
41 unsigned long flags;
42
43 if (pin < S3C2410_GPIO_BANKB) {
44 mask = 1 << S3C2410_GPIO_OFFSET(pin);
45 } else {
46 mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
47 }
48
49 switch (function) {
50 case S3C2410_GPIO_LEAVE:
51 mask = 0;
52 function = 0;
53 break;
54
55 case S3C2410_GPIO_INPUT:
56 case S3C2410_GPIO_OUTPUT:
57 case S3C2410_GPIO_SFN2:
58 case S3C2410_GPIO_SFN3:
59 if (pin < S3C2410_GPIO_BANKB) {
60 function -= 1;
61 function &= 1;
62 function <<= S3C2410_GPIO_OFFSET(pin);
63 } else {
64 function &= 3;
65 function <<= S3C2410_GPIO_OFFSET(pin)*2;
66 }
67 }
68
69 /* modify the specified register wwith IRQs off */
70
71 local_irq_save(flags);
72
73 con = __raw_readl(base + 0x00);
74 con &= ~mask;
75 con |= function;
76
77 __raw_writel(con, base + 0x00);
78
79 local_irq_restore(flags);
80}
81
82EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
83
84unsigned int s3c2410_gpio_getcfg(unsigned int pin)
85{
86 void __iomem *base = S3C24XX_GPIO_BASE(pin);
87 unsigned long val = __raw_readl(base);
88
89 if (pin < S3C2410_GPIO_BANKB) {
90 val >>= S3C2410_GPIO_OFFSET(pin);
91 val &= 1;
92 val += 1;
93 } else {
94 val >>= S3C2410_GPIO_OFFSET(pin)*2;
95 val &= 3;
96 }
97
98 return val | S3C2410_GPIO_INPUT;
99}
100
101EXPORT_SYMBOL(s3c2410_gpio_getcfg);
102
103void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
104{
105 void __iomem *base = S3C24XX_GPIO_BASE(pin);
106 unsigned long offs = S3C2410_GPIO_OFFSET(pin);
107 unsigned long flags;
108 unsigned long up;
109
110 if (pin < S3C2410_GPIO_BANKB)
111 return;
112
113 local_irq_save(flags);
114
115 up = __raw_readl(base + 0x08);
116 up &= ~(1L << offs);
117 up |= to << offs;
118 __raw_writel(up, base + 0x08);
119
120 local_irq_restore(flags);
121}
122
123EXPORT_SYMBOL(s3c2410_gpio_pullup);
124
125void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
126{
127 void __iomem *base = S3C24XX_GPIO_BASE(pin);
128 unsigned long offs = S3C2410_GPIO_OFFSET(pin);
129 unsigned long flags;
130 unsigned long dat;
131
132 local_irq_save(flags);
133
134 dat = __raw_readl(base + 0x04);
135 dat &= ~(1 << offs);
136 dat |= to << offs;
137 __raw_writel(dat, base + 0x04);
138
139 local_irq_restore(flags);
140}
141
142EXPORT_SYMBOL(s3c2410_gpio_setpin);
143
144unsigned int s3c2410_gpio_getpin(unsigned int pin)
145{
146 void __iomem *base = S3C24XX_GPIO_BASE(pin);
147 unsigned long offs = S3C2410_GPIO_OFFSET(pin);
148
149 return __raw_readl(base + 0x04) & (1<< offs);
150}
151
152EXPORT_SYMBOL(s3c2410_gpio_getpin);
153
154unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
155{
156 unsigned long flags;
157 unsigned long misccr;
158
159 local_irq_save(flags);
160 misccr = __raw_readl(S3C24XX_MISCCR);
161 misccr &= ~clear;
162 misccr ^= change;
163 __raw_writel(misccr, S3C24XX_MISCCR);
164 local_irq_restore(flags);
165
166 return misccr;
167}
168
169EXPORT_SYMBOL(s3c2410_modify_misccr);
170
171int s3c2410_gpio_getirq(unsigned int pin)
172{
173 if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
174 return -1; /* not valid interrupts */
175
176 if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
177 return -1; /* not valid pin */
178
179 if (pin < S3C2410_GPF4)
180 return (pin - S3C2410_GPF0) + IRQ_EINT0;
181
182 if (pin < S3C2410_GPG0)
183 return (pin - S3C2410_GPF4) + IRQ_EINT4;
184
185 return (pin - S3C2410_GPG0) + IRQ_EINT8;
186}
187
188EXPORT_SYMBOL(s3c2410_gpio_getirq);
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
new file mode 100644
index 000000000000..ce186398e3fd
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -0,0 +1,801 @@
1/* linux/arch/arm/plat-s3c24xx/irq.c
2 *
3 * Copyright (c) 2003,2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Changelog:
21 *
22 * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
23 * Fixed compile warnings
24 *
25 * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
26 * Fixed s3c_extirq_type
27 *
28 * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
29 * Addition of ADC/TC demux
30 *
31 * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de>
32 * Fix for set_irq_type() on low EINT numbers
33 *
34 * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
35 * Tidy up KF's patch and sort out new release
36 *
37 * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
38 * Add support for power management controls
39 *
40 * 04-Nov-2004 Ben Dooks
41 * Fix standard IRQ wake for EINT0..4 and RTC
42 *
43 * 22-Feb-2005 Ben Dooks
44 * Fixed edge-triggering on ADC IRQ
45 *
46 * 28-Jun-2005 Ben Dooks
47 * Mark IRQ_LCD valid
48 *
49 * 25-Jul-2005 Ben Dooks
50 * Split the S3C2440 IRQ code to seperate file
51*/
52
53#include <linux/init.h>
54#include <linux/module.h>
55#include <linux/interrupt.h>
56#include <linux/ioport.h>
57#include <linux/ptrace.h>
58#include <linux/sysdev.h>
59
60#include <asm/hardware.h>
61#include <asm/irq.h>
62#include <asm/io.h>
63
64#include <asm/mach/irq.h>
65
66#include <asm/arch/regs-irq.h>
67#include <asm/arch/regs-gpio.h>
68
69#include <asm/plat-s3c24xx/cpu.h>
70#include <asm/plat-s3c24xx/pm.h>
71#include <asm/plat-s3c24xx/irq.h>
72
73/* wakeup irq control */
74
75#ifdef CONFIG_PM
76
77/* state for IRQs over sleep */
78
79/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
80 *
81 * set bit to 1 in allow bitfield to enable the wakeup settings on it
82*/
83
84unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
85unsigned long s3c_irqwake_intmask = 0xffffffffL;
86unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
87unsigned long s3c_irqwake_eintmask = 0xffffffffL;
88
89int
90s3c_irq_wake(unsigned int irqno, unsigned int state)
91{
92 unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
93
94 if (!(s3c_irqwake_intallow & irqbit))
95 return -ENOENT;
96
97 printk(KERN_INFO "wake %s for irq %d\n",
98 state ? "enabled" : "disabled", irqno);
99
100 if (!state)
101 s3c_irqwake_intmask |= irqbit;
102 else
103 s3c_irqwake_intmask &= ~irqbit;
104
105 return 0;
106}
107
108static int
109s3c_irqext_wake(unsigned int irqno, unsigned int state)
110{
111 unsigned long bit = 1L << (irqno - EXTINT_OFF);
112
113 if (!(s3c_irqwake_eintallow & bit))
114 return -ENOENT;
115
116 printk(KERN_INFO "wake %s for irq %d\n",
117 state ? "enabled" : "disabled", irqno);
118
119 if (!state)
120 s3c_irqwake_eintmask |= bit;
121 else
122 s3c_irqwake_eintmask &= ~bit;
123
124 return 0;
125}
126
127#else
128#define s3c_irqext_wake NULL
129#define s3c_irq_wake NULL
130#endif
131
132
133static void
134s3c_irq_mask(unsigned int irqno)
135{
136 unsigned long mask;
137
138 irqno -= IRQ_EINT0;
139
140 mask = __raw_readl(S3C2410_INTMSK);
141 mask |= 1UL << irqno;
142 __raw_writel(mask, S3C2410_INTMSK);
143}
144
145static inline void
146s3c_irq_ack(unsigned int irqno)
147{
148 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
149
150 __raw_writel(bitval, S3C2410_SRCPND);
151 __raw_writel(bitval, S3C2410_INTPND);
152}
153
154static inline void
155s3c_irq_maskack(unsigned int irqno)
156{
157 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
158 unsigned long mask;
159
160 mask = __raw_readl(S3C2410_INTMSK);
161 __raw_writel(mask|bitval, S3C2410_INTMSK);
162
163 __raw_writel(bitval, S3C2410_SRCPND);
164 __raw_writel(bitval, S3C2410_INTPND);
165}
166
167
168static void
169s3c_irq_unmask(unsigned int irqno)
170{
171 unsigned long mask;
172
173 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
174 irqdbf2("s3c_irq_unmask %d\n", irqno);
175
176 irqno -= IRQ_EINT0;
177
178 mask = __raw_readl(S3C2410_INTMSK);
179 mask &= ~(1UL << irqno);
180 __raw_writel(mask, S3C2410_INTMSK);
181}
182
183struct irq_chip s3c_irq_level_chip = {
184 .name = "s3c-level",
185 .ack = s3c_irq_maskack,
186 .mask = s3c_irq_mask,
187 .unmask = s3c_irq_unmask,
188 .set_wake = s3c_irq_wake
189};
190
191static struct irq_chip s3c_irq_chip = {
192 .name = "s3c",
193 .ack = s3c_irq_ack,
194 .mask = s3c_irq_mask,
195 .unmask = s3c_irq_unmask,
196 .set_wake = s3c_irq_wake
197};
198
199static void
200s3c_irqext_mask(unsigned int irqno)
201{
202 unsigned long mask;
203
204 irqno -= EXTINT_OFF;
205
206 mask = __raw_readl(S3C24XX_EINTMASK);
207 mask |= ( 1UL << irqno);
208 __raw_writel(mask, S3C24XX_EINTMASK);
209}
210
211static void
212s3c_irqext_ack(unsigned int irqno)
213{
214 unsigned long req;
215 unsigned long bit;
216 unsigned long mask;
217
218 bit = 1UL << (irqno - EXTINT_OFF);
219
220 mask = __raw_readl(S3C24XX_EINTMASK);
221
222 __raw_writel(bit, S3C24XX_EINTPEND);
223
224 req = __raw_readl(S3C24XX_EINTPEND);
225 req &= ~mask;
226
227 /* not sure if we should be acking the parent irq... */
228
229 if (irqno <= IRQ_EINT7 ) {
230 if ((req & 0xf0) == 0)
231 s3c_irq_ack(IRQ_EINT4t7);
232 } else {
233 if ((req >> 8) == 0)
234 s3c_irq_ack(IRQ_EINT8t23);
235 }
236}
237
238static void
239s3c_irqext_unmask(unsigned int irqno)
240{
241 unsigned long mask;
242
243 irqno -= EXTINT_OFF;
244
245 mask = __raw_readl(S3C24XX_EINTMASK);
246 mask &= ~( 1UL << irqno);
247 __raw_writel(mask, S3C24XX_EINTMASK);
248}
249
250int
251s3c_irqext_type(unsigned int irq, unsigned int type)
252{
253 void __iomem *extint_reg;
254 void __iomem *gpcon_reg;
255 unsigned long gpcon_offset, extint_offset;
256 unsigned long newvalue = 0, value;
257
258 if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
259 {
260 gpcon_reg = S3C2410_GPFCON;
261 extint_reg = S3C24XX_EXTINT0;
262 gpcon_offset = (irq - IRQ_EINT0) * 2;
263 extint_offset = (irq - IRQ_EINT0) * 4;
264 }
265 else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
266 {
267 gpcon_reg = S3C2410_GPFCON;
268 extint_reg = S3C24XX_EXTINT0;
269 gpcon_offset = (irq - (EXTINT_OFF)) * 2;
270 extint_offset = (irq - (EXTINT_OFF)) * 4;
271 }
272 else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
273 {
274 gpcon_reg = S3C2410_GPGCON;
275 extint_reg = S3C24XX_EXTINT1;
276 gpcon_offset = (irq - IRQ_EINT8) * 2;
277 extint_offset = (irq - IRQ_EINT8) * 4;
278 }
279 else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
280 {
281 gpcon_reg = S3C2410_GPGCON;
282 extint_reg = S3C24XX_EXTINT2;
283 gpcon_offset = (irq - IRQ_EINT8) * 2;
284 extint_offset = (irq - IRQ_EINT16) * 4;
285 } else
286 return -1;
287
288 /* Set the GPIO to external interrupt mode */
289 value = __raw_readl(gpcon_reg);
290 value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
291 __raw_writel(value, gpcon_reg);
292
293 /* Set the external interrupt to pointed trigger type */
294 switch (type)
295 {
296 case IRQT_NOEDGE:
297 printk(KERN_WARNING "No edge setting!\n");
298 break;
299
300 case IRQT_RISING:
301 newvalue = S3C2410_EXTINT_RISEEDGE;
302 break;
303
304 case IRQT_FALLING:
305 newvalue = S3C2410_EXTINT_FALLEDGE;
306 break;
307
308 case IRQT_BOTHEDGE:
309 newvalue = S3C2410_EXTINT_BOTHEDGE;
310 break;
311
312 case IRQT_LOW:
313 newvalue = S3C2410_EXTINT_LOWLEV;
314 break;
315
316 case IRQT_HIGH:
317 newvalue = S3C2410_EXTINT_HILEV;
318 break;
319
320 default:
321 printk(KERN_ERR "No such irq type %d", type);
322 return -1;
323 }
324
325 value = __raw_readl(extint_reg);
326 value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
327 __raw_writel(value, extint_reg);
328
329 return 0;
330}
331
332static struct irq_chip s3c_irqext_chip = {
333 .name = "s3c-ext",
334 .mask = s3c_irqext_mask,
335 .unmask = s3c_irqext_unmask,
336 .ack = s3c_irqext_ack,
337 .set_type = s3c_irqext_type,
338 .set_wake = s3c_irqext_wake
339};
340
341static struct irq_chip s3c_irq_eint0t4 = {
342 .name = "s3c-ext0",
343 .ack = s3c_irq_ack,
344 .mask = s3c_irq_mask,
345 .unmask = s3c_irq_unmask,
346 .set_wake = s3c_irq_wake,
347 .set_type = s3c_irqext_type,
348};
349
350/* mask values for the parent registers for each of the interrupt types */
351
352#define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0))
353#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
354#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
355#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
356
357
358/* UART0 */
359
360static void
361s3c_irq_uart0_mask(unsigned int irqno)
362{
363 s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
364}
365
366static void
367s3c_irq_uart0_unmask(unsigned int irqno)
368{
369 s3c_irqsub_unmask(irqno, INTMSK_UART0);
370}
371
372static void
373s3c_irq_uart0_ack(unsigned int irqno)
374{
375 s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
376}
377
378static struct irq_chip s3c_irq_uart0 = {
379 .name = "s3c-uart0",
380 .mask = s3c_irq_uart0_mask,
381 .unmask = s3c_irq_uart0_unmask,
382 .ack = s3c_irq_uart0_ack,
383};
384
385/* UART1 */
386
387static void
388s3c_irq_uart1_mask(unsigned int irqno)
389{
390 s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
391}
392
393static void
394s3c_irq_uart1_unmask(unsigned int irqno)
395{
396 s3c_irqsub_unmask(irqno, INTMSK_UART1);
397}
398
399static void
400s3c_irq_uart1_ack(unsigned int irqno)
401{
402 s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
403}
404
405static struct irq_chip s3c_irq_uart1 = {
406 .name = "s3c-uart1",
407 .mask = s3c_irq_uart1_mask,
408 .unmask = s3c_irq_uart1_unmask,
409 .ack = s3c_irq_uart1_ack,
410};
411
412/* UART2 */
413
414static void
415s3c_irq_uart2_mask(unsigned int irqno)
416{
417 s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
418}
419
420static void
421s3c_irq_uart2_unmask(unsigned int irqno)
422{
423 s3c_irqsub_unmask(irqno, INTMSK_UART2);
424}
425
426static void
427s3c_irq_uart2_ack(unsigned int irqno)
428{
429 s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
430}
431
432static struct irq_chip s3c_irq_uart2 = {
433 .name = "s3c-uart2",
434 .mask = s3c_irq_uart2_mask,
435 .unmask = s3c_irq_uart2_unmask,
436 .ack = s3c_irq_uart2_ack,
437};
438
439/* ADC and Touchscreen */
440
441static void
442s3c_irq_adc_mask(unsigned int irqno)
443{
444 s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
445}
446
447static void
448s3c_irq_adc_unmask(unsigned int irqno)
449{
450 s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
451}
452
453static void
454s3c_irq_adc_ack(unsigned int irqno)
455{
456 s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9);
457}
458
459static struct irq_chip s3c_irq_adc = {
460 .name = "s3c-adc",
461 .mask = s3c_irq_adc_mask,
462 .unmask = s3c_irq_adc_unmask,
463 .ack = s3c_irq_adc_ack,
464};
465
466/* irq demux for adc */
467static void s3c_irq_demux_adc(unsigned int irq,
468 struct irq_desc *desc)
469{
470 unsigned int subsrc, submsk;
471 unsigned int offset = 9;
472 struct irq_desc *mydesc;
473
474 /* read the current pending interrupts, and the mask
475 * for what it is available */
476
477 subsrc = __raw_readl(S3C2410_SUBSRCPND);
478 submsk = __raw_readl(S3C2410_INTSUBMSK);
479
480 subsrc &= ~submsk;
481 subsrc >>= offset;
482 subsrc &= 3;
483
484 if (subsrc != 0) {
485 if (subsrc & 1) {
486 mydesc = irq_desc + IRQ_TC;
487 desc_handle_irq(IRQ_TC, mydesc);
488 }
489 if (subsrc & 2) {
490 mydesc = irq_desc + IRQ_ADC;
491 desc_handle_irq(IRQ_ADC, mydesc);
492 }
493 }
494}
495
496static void s3c_irq_demux_uart(unsigned int start)
497{
498 unsigned int subsrc, submsk;
499 unsigned int offset = start - IRQ_S3CUART_RX0;
500 struct irq_desc *desc;
501
502 /* read the current pending interrupts, and the mask
503 * for what it is available */
504
505 subsrc = __raw_readl(S3C2410_SUBSRCPND);
506 submsk = __raw_readl(S3C2410_INTSUBMSK);
507
508 irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
509 start, offset, subsrc, submsk);
510
511 subsrc &= ~submsk;
512 subsrc >>= offset;
513 subsrc &= 7;
514
515 if (subsrc != 0) {
516 desc = irq_desc + start;
517
518 if (subsrc & 1)
519 desc_handle_irq(start, desc);
520
521 desc++;
522
523 if (subsrc & 2)
524 desc_handle_irq(start+1, desc);
525
526 desc++;
527
528 if (subsrc & 4)
529 desc_handle_irq(start+2, desc);
530 }
531}
532
533/* uart demux entry points */
534
535static void
536s3c_irq_demux_uart0(unsigned int irq,
537 struct irq_desc *desc)
538{
539 irq = irq;
540 s3c_irq_demux_uart(IRQ_S3CUART_RX0);
541}
542
543static void
544s3c_irq_demux_uart1(unsigned int irq,
545 struct irq_desc *desc)
546{
547 irq = irq;
548 s3c_irq_demux_uart(IRQ_S3CUART_RX1);
549}
550
551static void
552s3c_irq_demux_uart2(unsigned int irq,
553 struct irq_desc *desc)
554{
555 irq = irq;
556 s3c_irq_demux_uart(IRQ_S3CUART_RX2);
557}
558
559static void
560s3c_irq_demux_extint8(unsigned int irq,
561 struct irq_desc *desc)
562{
563 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
564 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
565
566 eintpnd &= ~eintmsk;
567 eintpnd &= ~0xff; /* ignore lower irqs */
568
569 /* we may as well handle all the pending IRQs here */
570
571 while (eintpnd) {
572 irq = __ffs(eintpnd);
573 eintpnd &= ~(1<<irq);
574
575 irq += (IRQ_EINT4 - 4);
576 desc_handle_irq(irq, irq_desc + irq);
577 }
578
579}
580
581static void
582s3c_irq_demux_extint4t7(unsigned int irq,
583 struct irq_desc *desc)
584{
585 unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
586 unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
587
588 eintpnd &= ~eintmsk;
589 eintpnd &= 0xff; /* only lower irqs */
590
591 /* we may as well handle all the pending IRQs here */
592
593 while (eintpnd) {
594 irq = __ffs(eintpnd);
595 eintpnd &= ~(1<<irq);
596
597 irq += (IRQ_EINT4 - 4);
598
599 desc_handle_irq(irq, irq_desc + irq);
600 }
601}
602
603#ifdef CONFIG_PM
604
605static struct sleep_save irq_save[] = {
606 SAVE_ITEM(S3C2410_INTMSK),
607 SAVE_ITEM(S3C2410_INTSUBMSK),
608};
609
610/* the extint values move between the s3c2410/s3c2440 and the s3c2412
611 * so we use an array to hold them, and to calculate the address of
612 * the register at run-time
613*/
614
615static unsigned long save_extint[3];
616static unsigned long save_eintflt[4];
617static unsigned long save_eintmask;
618
619int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
620{
621 unsigned int i;
622
623 for (i = 0; i < ARRAY_SIZE(save_extint); i++)
624 save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
625
626 for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
627 save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
628
629 s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
630 save_eintmask = __raw_readl(S3C24XX_EINTMASK);
631
632 return 0;
633}
634
635int s3c24xx_irq_resume(struct sys_device *dev)
636{
637 unsigned int i;
638
639 for (i = 0; i < ARRAY_SIZE(save_extint); i++)
640 __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
641
642 for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
643 __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
644
645 s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
646 __raw_writel(save_eintmask, S3C24XX_EINTMASK);
647
648 return 0;
649}
650
651#else
652#define s3c24xx_irq_suspend NULL
653#define s3c24xx_irq_resume NULL
654#endif
655
656/* s3c24xx_init_irq
657 *
658 * Initialise S3C2410 IRQ system
659*/
660
661void __init s3c24xx_init_irq(void)
662{
663 unsigned long pend;
664 unsigned long last;
665 int irqno;
666 int i;
667
668 irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
669
670 /* first, clear all interrupts pending... */
671
672 last = 0;
673 for (i = 0; i < 4; i++) {
674 pend = __raw_readl(S3C24XX_EINTPEND);
675
676 if (pend == 0 || pend == last)
677 break;
678
679 __raw_writel(pend, S3C24XX_EINTPEND);
680 printk("irq: clearing pending ext status %08x\n", (int)pend);
681 last = pend;
682 }
683
684 last = 0;
685 for (i = 0; i < 4; i++) {
686 pend = __raw_readl(S3C2410_INTPND);
687
688 if (pend == 0 || pend == last)
689 break;
690
691 __raw_writel(pend, S3C2410_SRCPND);
692 __raw_writel(pend, S3C2410_INTPND);
693 printk("irq: clearing pending status %08x\n", (int)pend);
694 last = pend;
695 }
696
697 last = 0;
698 for (i = 0; i < 4; i++) {
699 pend = __raw_readl(S3C2410_SUBSRCPND);
700
701 if (pend == 0 || pend == last)
702 break;
703
704 printk("irq: clearing subpending status %08x\n", (int)pend);
705 __raw_writel(pend, S3C2410_SUBSRCPND);
706 last = pend;
707 }
708
709 /* register the main interrupts */
710
711 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
712
713 for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
714 /* set all the s3c2410 internal irqs */
715
716 switch (irqno) {
717 /* deal with the special IRQs (cascaded) */
718
719 case IRQ_EINT4t7:
720 case IRQ_EINT8t23:
721 case IRQ_UART0:
722 case IRQ_UART1:
723 case IRQ_UART2:
724 case IRQ_ADCPARENT:
725 set_irq_chip(irqno, &s3c_irq_level_chip);
726 set_irq_handler(irqno, handle_level_irq);
727 break;
728
729 case IRQ_RESERVED6:
730 case IRQ_RESERVED24:
731 /* no IRQ here */
732 break;
733
734 default:
735 //irqdbf("registering irq %d (s3c irq)\n", irqno);
736 set_irq_chip(irqno, &s3c_irq_chip);
737 set_irq_handler(irqno, handle_edge_irq);
738 set_irq_flags(irqno, IRQF_VALID);
739 }
740 }
741
742 /* setup the cascade irq handlers */
743
744 set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
745 set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
746
747 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
748 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
749 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
750 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
751
752 /* external interrupts */
753
754 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
755 irqdbf("registering irq %d (ext int)\n", irqno);
756 set_irq_chip(irqno, &s3c_irq_eint0t4);
757 set_irq_handler(irqno, handle_edge_irq);
758 set_irq_flags(irqno, IRQF_VALID);
759 }
760
761 for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
762 irqdbf("registering irq %d (extended s3c irq)\n", irqno);
763 set_irq_chip(irqno, &s3c_irqext_chip);
764 set_irq_handler(irqno, handle_edge_irq);
765 set_irq_flags(irqno, IRQF_VALID);
766 }
767
768 /* register the uart interrupts */
769
770 irqdbf("s3c2410: registering external interrupts\n");
771
772 for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
773 irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
774 set_irq_chip(irqno, &s3c_irq_uart0);
775 set_irq_handler(irqno, handle_level_irq);
776 set_irq_flags(irqno, IRQF_VALID);
777 }
778
779 for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
780 irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
781 set_irq_chip(irqno, &s3c_irq_uart1);
782 set_irq_handler(irqno, handle_level_irq);
783 set_irq_flags(irqno, IRQF_VALID);
784 }
785
786 for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
787 irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
788 set_irq_chip(irqno, &s3c_irq_uart2);
789 set_irq_handler(irqno, handle_level_irq);
790 set_irq_flags(irqno, IRQF_VALID);
791 }
792
793 for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
794 irqdbf("registering irq %d (s3c adc irq)\n", irqno);
795 set_irq_chip(irqno, &s3c_irq_adc);
796 set_irq_handler(irqno, handle_edge_irq);
797 set_irq_flags(irqno, IRQF_VALID);
798 }
799
800 irqdbf("s3c2410: registered interrupt handlers\n");
801}
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/plat-s3c24xx/pm-simtec.c
index 619133eb7168..bd965f2feeca 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/plat-s3c24xx/pm-simtec.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/pm-simtec.c 1/* linux/arch/arm/plat-s3c24xx/pm-simtec.c
2 * 2 *
3 * Copyright (c) 2004 Simtec Electronics 3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -32,7 +32,7 @@
32 32
33#include <asm/mach-types.h> 33#include <asm/mach-types.h>
34 34
35#include "pm.h" 35#include <asm/plat-s3c24xx/pm.h>
36 36
37#define COPYRIGHT ", (c) 2005 Simtec Electronics" 37#define COPYRIGHT ", (c) 2005 Simtec Electronics"
38 38
diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c
new file mode 100644
index 000000000000..ecf68d611904
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/pm.c
@@ -0,0 +1,659 @@
1/* linux/arch/arm/plat-s3c24xx/pm.c
2 *
3 * Copyright (c) 2004,2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C24XX Power Manager (Suspend-To-RAM) support
7 *
8 * See Documentation/arm/Samsung-S3C24XX/Suspend.txt for more information
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Parts based on arch/arm/mach-pxa/pm.c
25 *
26 * Thanks to Dimitry Andric for debugging
27*/
28
29#include <linux/init.h>
30#include <linux/suspend.h>
31#include <linux/errno.h>
32#include <linux/time.h>
33#include <linux/interrupt.h>
34#include <linux/crc32.h>
35#include <linux/ioport.h>
36#include <linux/delay.h>
37#include <linux/serial_core.h>
38
39#include <asm/cacheflush.h>
40#include <asm/hardware.h>
41#include <asm/io.h>
42
43#include <asm/arch/regs-serial.h>
44#include <asm/arch/regs-clock.h>
45#include <asm/arch/regs-gpio.h>
46#include <asm/arch/regs-mem.h>
47#include <asm/arch/regs-irq.h>
48
49#include <asm/mach/time.h>
50
51#include <asm/plat-s3c24xx/pm.h>
52
53/* for external use */
54
55unsigned long s3c_pm_flags;
56
57#define PFX "s3c24xx-pm: "
58
59static struct sleep_save core_save[] = {
60 SAVE_ITEM(S3C2410_LOCKTIME),
61 SAVE_ITEM(S3C2410_CLKCON),
62
63 /* we restore the timings here, with the proviso that the board
64 * brings the system up in an slower, or equal frequency setting
65 * to the original system.
66 *
67 * if we cannot guarantee this, then things are going to go very
68 * wrong here, as we modify the refresh and both pll settings.
69 */
70
71 SAVE_ITEM(S3C2410_BWSCON),
72 SAVE_ITEM(S3C2410_BANKCON0),
73 SAVE_ITEM(S3C2410_BANKCON1),
74 SAVE_ITEM(S3C2410_BANKCON2),
75 SAVE_ITEM(S3C2410_BANKCON3),
76 SAVE_ITEM(S3C2410_BANKCON4),
77 SAVE_ITEM(S3C2410_BANKCON5),
78
79 SAVE_ITEM(S3C2410_CLKDIVN),
80 SAVE_ITEM(S3C2410_MPLLCON),
81 SAVE_ITEM(S3C2410_UPLLCON),
82 SAVE_ITEM(S3C2410_CLKSLOW),
83 SAVE_ITEM(S3C2410_REFRESH),
84};
85
86static struct sleep_save gpio_save[] = {
87 SAVE_ITEM(S3C2410_GPACON),
88 SAVE_ITEM(S3C2410_GPADAT),
89
90 SAVE_ITEM(S3C2410_GPBCON),
91 SAVE_ITEM(S3C2410_GPBDAT),
92 SAVE_ITEM(S3C2410_GPBUP),
93
94 SAVE_ITEM(S3C2410_GPCCON),
95 SAVE_ITEM(S3C2410_GPCDAT),
96 SAVE_ITEM(S3C2410_GPCUP),
97
98 SAVE_ITEM(S3C2410_GPDCON),
99 SAVE_ITEM(S3C2410_GPDDAT),
100 SAVE_ITEM(S3C2410_GPDUP),
101
102 SAVE_ITEM(S3C2410_GPECON),
103 SAVE_ITEM(S3C2410_GPEDAT),
104 SAVE_ITEM(S3C2410_GPEUP),
105
106 SAVE_ITEM(S3C2410_GPFCON),
107 SAVE_ITEM(S3C2410_GPFDAT),
108 SAVE_ITEM(S3C2410_GPFUP),
109
110 SAVE_ITEM(S3C2410_GPGCON),
111 SAVE_ITEM(S3C2410_GPGDAT),
112 SAVE_ITEM(S3C2410_GPGUP),
113
114 SAVE_ITEM(S3C2410_GPHCON),
115 SAVE_ITEM(S3C2410_GPHDAT),
116 SAVE_ITEM(S3C2410_GPHUP),
117
118 SAVE_ITEM(S3C2410_DCLKCON),
119};
120
121#ifdef CONFIG_S3C2410_PM_DEBUG
122
123#define SAVE_UART(va) \
124 SAVE_ITEM((va) + S3C2410_ULCON), \
125 SAVE_ITEM((va) + S3C2410_UCON), \
126 SAVE_ITEM((va) + S3C2410_UFCON), \
127 SAVE_ITEM((va) + S3C2410_UMCON), \
128 SAVE_ITEM((va) + S3C2410_UBRDIV)
129
130static struct sleep_save uart_save[] = {
131 SAVE_UART(S3C24XX_VA_UART0),
132 SAVE_UART(S3C24XX_VA_UART1),
133#ifndef CONFIG_CPU_S3C2400
134 SAVE_UART(S3C24XX_VA_UART2),
135#endif
136};
137
138/* debug
139 *
140 * we send the debug to printascii() to allow it to be seen if the
141 * system never wakes up from the sleep
142*/
143
144extern void printascii(const char *);
145
146void pm_dbg(const char *fmt, ...)
147{
148 va_list va;
149 char buff[256];
150
151 va_start(va, fmt);
152 vsprintf(buff, fmt, va);
153 va_end(va);
154
155 printascii(buff);
156}
157
158static void s3c2410_pm_debug_init(void)
159{
160 unsigned long tmp = __raw_readl(S3C2410_CLKCON);
161
162 /* re-start uart clocks */
163 tmp |= S3C2410_CLKCON_UART0;
164 tmp |= S3C2410_CLKCON_UART1;
165 tmp |= S3C2410_CLKCON_UART2;
166
167 __raw_writel(tmp, S3C2410_CLKCON);
168 udelay(10);
169}
170
171#define DBG(fmt...) pm_dbg(fmt)
172#else
173#define DBG(fmt...) printk(KERN_DEBUG fmt)
174
175#define s3c2410_pm_debug_init() do { } while(0)
176
177static struct sleep_save uart_save[] = {};
178#endif
179
180#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
181
182/* suspend checking code...
183 *
184 * this next area does a set of crc checks over all the installed
185 * memory, so the system can verify if the resume was ok.
186 *
187 * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
188 * increasing it will mean that the area corrupted will be less easy to spot,
189 * and reducing the size will cause the CRC save area to grow
190*/
191
192#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
193
194static u32 crc_size; /* size needed for the crc block */
195static u32 *crcs; /* allocated over suspend/resume */
196
197typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
198
199/* s3c2410_pm_run_res
200 *
201 * go thorugh the given resource list, and look for system ram
202*/
203
204static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
205{
206 while (ptr != NULL) {
207 if (ptr->child != NULL)
208 s3c2410_pm_run_res(ptr->child, fn, arg);
209
210 if ((ptr->flags & IORESOURCE_MEM) &&
211 strcmp(ptr->name, "System RAM") == 0) {
212 DBG("Found system RAM at %08lx..%08lx\n",
213 ptr->start, ptr->end);
214 arg = (fn)(ptr, arg);
215 }
216
217 ptr = ptr->sibling;
218 }
219}
220
221static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
222{
223 s3c2410_pm_run_res(&iomem_resource, fn, arg);
224}
225
226static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
227{
228 u32 size = (u32)(res->end - res->start)+1;
229
230 size += CHECK_CHUNKSIZE-1;
231 size /= CHECK_CHUNKSIZE;
232
233 DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
234
235 *val += size * sizeof(u32);
236 return val;
237}
238
239/* s3c2410_pm_prepare_check
240 *
241 * prepare the necessary information for creating the CRCs. This
242 * must be done before the final save, as it will require memory
243 * allocating, and thus touching bits of the kernel we do not
244 * know about.
245*/
246
247static void s3c2410_pm_check_prepare(void)
248{
249 crc_size = 0;
250
251 s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
252
253 DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
254
255 crcs = kmalloc(crc_size+4, GFP_KERNEL);
256 if (crcs == NULL)
257 printk(KERN_ERR "Cannot allocated CRC save area\n");
258}
259
260static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
261{
262 unsigned long addr, left;
263
264 for (addr = res->start; addr < res->end;
265 addr += CHECK_CHUNKSIZE) {
266 left = res->end - addr;
267
268 if (left > CHECK_CHUNKSIZE)
269 left = CHECK_CHUNKSIZE;
270
271 *val = crc32_le(~0, phys_to_virt(addr), left);
272 val++;
273 }
274
275 return val;
276}
277
278/* s3c2410_pm_check_store
279 *
280 * compute the CRC values for the memory blocks before the final
281 * sleep.
282*/
283
284static void s3c2410_pm_check_store(void)
285{
286 if (crcs != NULL)
287 s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
288}
289
290/* in_region
291 *
292 * return TRUE if the area defined by ptr..ptr+size contatins the
293 * what..what+whatsz
294*/
295
296static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
297{
298 if ((what+whatsz) < ptr)
299 return 0;
300
301 if (what > (ptr+size))
302 return 0;
303
304 return 1;
305}
306
307static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
308{
309 void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
310 unsigned long addr;
311 unsigned long left;
312 void *ptr;
313 u32 calc;
314
315 for (addr = res->start; addr < res->end;
316 addr += CHECK_CHUNKSIZE) {
317 left = res->end - addr;
318
319 if (left > CHECK_CHUNKSIZE)
320 left = CHECK_CHUNKSIZE;
321
322 ptr = phys_to_virt(addr);
323
324 if (in_region(ptr, left, crcs, crc_size)) {
325 DBG("skipping %08lx, has crc block in\n", addr);
326 goto skip_check;
327 }
328
329 if (in_region(ptr, left, save_at, 32*4 )) {
330 DBG("skipping %08lx, has save block in\n", addr);
331 goto skip_check;
332 }
333
334 /* calculate and check the checksum */
335
336 calc = crc32_le(~0, ptr, left);
337 if (calc != *val) {
338 printk(KERN_ERR PFX "Restore CRC error at "
339 "%08lx (%08x vs %08x)\n", addr, calc, *val);
340
341 DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
342 addr, calc, *val);
343 }
344
345 skip_check:
346 val++;
347 }
348
349 return val;
350}
351
352/* s3c2410_pm_check_restore
353 *
354 * check the CRCs after the restore event and free the memory used
355 * to hold them
356*/
357
358static void s3c2410_pm_check_restore(void)
359{
360 if (crcs != NULL) {
361 s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
362 kfree(crcs);
363 crcs = NULL;
364 }
365}
366
367#else
368
369#define s3c2410_pm_check_prepare() do { } while(0)
370#define s3c2410_pm_check_restore() do { } while(0)
371#define s3c2410_pm_check_store() do { } while(0)
372#endif
373
374/* helper functions to save and restore register state */
375
376void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
377{
378 for (; count > 0; count--, ptr++) {
379 ptr->val = __raw_readl(ptr->reg);
380 DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
381 }
382}
383
384/* s3c2410_pm_do_restore
385 *
386 * restore the system from the given list of saved registers
387 *
388 * Note, we do not use DBG() in here, as the system may not have
389 * restore the UARTs state yet
390*/
391
392void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
393{
394 for (; count > 0; count--, ptr++) {
395 printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
396 ptr->reg, ptr->val, __raw_readl(ptr->reg));
397
398 __raw_writel(ptr->val, ptr->reg);
399 }
400}
401
402/* s3c2410_pm_do_restore_core
403 *
404 * similar to s3c2410_pm_do_restore_core
405 *
406 * WARNING: Do not put any debug in here that may effect memory or use
407 * peripherals, as things may be changing!
408*/
409
410static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
411{
412 for (; count > 0; count--, ptr++) {
413 __raw_writel(ptr->val, ptr->reg);
414 }
415}
416
417/* s3c2410_pm_show_resume_irqs
418 *
419 * print any IRQs asserted at resume time (ie, we woke from)
420*/
421
422static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
423 unsigned long mask)
424{
425 int i;
426
427 which &= ~mask;
428
429 for (i = 0; i <= 31; i++) {
430 if ((which) & (1L<<i)) {
431 DBG("IRQ %d asserted at resume\n", start+i);
432 }
433 }
434}
435
436/* s3c2410_pm_check_resume_pin
437 *
438 * check to see if the pin is configured correctly for sleep mode, and
439 * make any necessary adjustments if it is not
440*/
441
442static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
443{
444 unsigned long irqstate;
445 unsigned long pinstate;
446 int irq = s3c2410_gpio_getirq(pin);
447
448 if (irqoffs < 4)
449 irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
450 else
451 irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
452
453 pinstate = s3c2410_gpio_getcfg(pin);
454
455 if (!irqstate) {
456 if (pinstate == S3C2410_GPIO_IRQ)
457 DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
458 } else {
459 if (pinstate == S3C2410_GPIO_IRQ) {
460 DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
461 s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
462 }
463 }
464}
465
466/* s3c2410_pm_configure_extint
467 *
468 * configure all external interrupt pins
469*/
470
471static void s3c2410_pm_configure_extint(void)
472{
473 int pin;
474
475 /* for each of the external interrupts (EINT0..EINT15) we
476 * need to check wether it is an external interrupt source,
477 * and then configure it as an input if it is not
478 */
479
480 for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
481 s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
482 }
483
484 for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
485 s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
486 }
487}
488
489void (*pm_cpu_prep)(void);
490void (*pm_cpu_sleep)(void);
491
492#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
493
494/* s3c2410_pm_enter
495 *
496 * central control for sleep/resume process
497*/
498
499static int s3c2410_pm_enter(suspend_state_t state)
500{
501 unsigned long regs_save[16];
502
503 /* ensure the debug is initialised (if enabled) */
504
505 s3c2410_pm_debug_init();
506
507 DBG("s3c2410_pm_enter(%d)\n", state);
508
509 if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
510 printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
511 return -EINVAL;
512 }
513
514 if (state != PM_SUSPEND_MEM) {
515 printk(KERN_ERR PFX "error: only PM_SUSPEND_MEM supported\n");
516 return -EINVAL;
517 }
518
519 /* check if we have anything to wake-up with... bad things seem
520 * to happen if you suspend with no wakeup (system will often
521 * require a full power-cycle)
522 */
523
524 if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
525 !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
526 printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
527 printk(KERN_ERR PFX "Aborting sleep\n");
528 return -EINVAL;
529 }
530
531 /* prepare check area if configured */
532
533 s3c2410_pm_check_prepare();
534
535 /* store the physical address of the register recovery block */
536
537 s3c2410_sleep_save_phys = virt_to_phys(regs_save);
538
539 DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
540
541 /* save all necessary core registers not covered by the drivers */
542
543 s3c2410_pm_do_save(gpio_save, ARRAY_SIZE(gpio_save));
544 s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
545 s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
546
547 /* set the irq configuration for wake */
548
549 s3c2410_pm_configure_extint();
550
551 DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
552 s3c_irqwake_intmask, s3c_irqwake_eintmask);
553
554 __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
555 __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
556
557 /* ack any outstanding external interrupts before we go to sleep */
558
559 __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
560 __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
561 __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
562
563 /* call cpu specific preperation */
564
565 pm_cpu_prep();
566
567 /* flush cache back to ram */
568
569 flush_cache_all();
570
571 s3c2410_pm_check_store();
572
573 /* send the cpu to sleep... */
574
575 __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
576
577 /* s3c2410_cpu_save will also act as our return point from when
578 * we resume as it saves its own register state, so use the return
579 * code to differentiate return from save and return from sleep */
580
581 if (s3c2410_cpu_save(regs_save) == 0) {
582 flush_cache_all();
583 pm_cpu_sleep();
584 }
585
586 /* restore the cpu state */
587
588 cpu_init();
589
590 /* restore the system state */
591
592 s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
593 s3c2410_pm_do_restore(gpio_save, ARRAY_SIZE(gpio_save));
594 s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
595
596 s3c2410_pm_debug_init();
597
598 /* check what irq (if any) restored the system */
599
600 DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
601 __raw_readl(S3C2410_SRCPND),
602 __raw_readl(S3C2410_EINTPEND));
603
604 s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
605 s3c_irqwake_intmask);
606
607 s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
608 s3c_irqwake_eintmask);
609
610 DBG("post sleep, preparing to return\n");
611
612 s3c2410_pm_check_restore();
613
614 /* ok, let's return from sleep */
615
616 DBG("S3C2410 PM Resume (post-restore)\n");
617 return 0;
618}
619
620/*
621 * Called after processes are frozen, but before we shut down devices.
622 */
623static int s3c2410_pm_prepare(suspend_state_t state)
624{
625 return 0;
626}
627
628/*
629 * Called after devices are re-setup, but before processes are thawed.
630 */
631static int s3c2410_pm_finish(suspend_state_t state)
632{
633 return 0;
634}
635
636/*
637 * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
638 */
639static struct pm_ops s3c2410_pm_ops = {
640 .pm_disk_mode = PM_DISK_FIRMWARE,
641 .prepare = s3c2410_pm_prepare,
642 .enter = s3c2410_pm_enter,
643 .finish = s3c2410_pm_finish,
644};
645
646/* s3c2410_pm_init
647 *
648 * Attach the power management functions. This should be called
649 * from the board specific initialisation if the board supports
650 * it.
651*/
652
653int __init s3c2410_pm_init(void)
654{
655 printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
656
657 pm_set_ops(&s3c2410_pm_ops);
658 return 0;
659}
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/plat-s3c24xx/s3c244x-irq.c
index ede94636a72a..a0e39d894014 100644
--- a/arch/arm/mach-s3c2410/s3c244x-irq.c
+++ b/arch/arm/plat-s3c24xx/s3c244x-irq.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/s3c244x-irq.c 1/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
2 * 2 *
3 * Copyright (c) 2003,2004 Simtec Electronics 3 * Copyright (c) 2003,2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
@@ -35,9 +35,9 @@
35#include <asm/arch/regs-irq.h> 35#include <asm/arch/regs-irq.h>
36#include <asm/arch/regs-gpio.h> 36#include <asm/arch/regs-gpio.h>
37 37
38#include "cpu.h" 38#include <asm/plat-s3c24xx/cpu.h>
39#include "pm.h" 39#include <asm/plat-s3c24xx/pm.h>
40#include "irq.h" 40#include <asm/plat-s3c24xx/irq.h>
41 41
42/* camera irq */ 42/* camera irq */
43 43
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c
index 23c7494ad10d..767f2e9a3a55 100644
--- a/arch/arm/mach-s3c2410/s3c244x.c
+++ b/arch/arm/plat-s3c24xx/s3c244x.c
@@ -1,9 +1,9 @@
1/* linux/arch/arm/mach-s3c2410/s3c244x.c 1/* linux/arch/arm/plat-s3c24xx/s3c244x.c
2 * 2 *
3 * Copyright (c) 2004-2006 Simtec Electronics 3 * Copyright (c) 2004-2006 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
5 * 5 *
6 * Samsung S3C2440 and S3C2442 Mobile CPU support 6 * Samsung S3C2440 and S3C2442 Mobile CPU support (not S3C2443)
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
@@ -35,13 +35,13 @@
35#include <asm/arch/regs-gpioj.h> 35#include <asm/arch/regs-gpioj.h>
36#include <asm/arch/regs-dsc.h> 36#include <asm/arch/regs-dsc.h>
37 37
38#include "s3c2410.h" 38#include <asm/plat-s3c24xx/s3c2410.h>
39#include "s3c2440.h" 39#include <asm/plat-s3c24xx/s3c2440.h>
40#include "s3c244x.h" 40#include "s3c244x.h"
41#include "clock.h" 41#include <asm/plat-s3c24xx/clock.h>
42#include "devs.h" 42#include <asm/plat-s3c24xx/devs.h>
43#include "cpu.h" 43#include <asm/plat-s3c24xx/cpu.h>
44#include "pm.h" 44#include <asm/plat-s3c24xx/pm.h>
45 45
46static struct map_desc s3c244x_iodesc[] __initdata = { 46static struct map_desc s3c244x_iodesc[] __initdata = {
47 IODESC_ENT(CLKPWR), 47 IODESC_ENT(CLKPWR),
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/plat-s3c24xx/s3c244x.h
index 1488c1eb37e6..f8ed17676a35 100644
--- a/arch/arm/mach-s3c2410/s3c244x.h
+++ b/arch/arm/plat-s3c24xx/s3c244x.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/s3c244x.h 1/* linux/arch/arm/plat-s3c24xx/s3c244x.h
2 * 2 *
3 * Copyright (c) 2004-2005 Simtec Electronics 3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk> 4 * Ben Dooks <ben@simtec.co.uk>
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
new file mode 100644
index 000000000000..435349dc3243
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -0,0 +1,157 @@
1/* linux/arch/arm/mach-s3c2410/sleep.S
2 *
3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * S3C2410 Power Manager (Suspend-To-RAM) support
7 *
8 * Based on PXA/SA1100 sleep code by:
9 * Nicolas Pitre, (c) 2002 Monta Vista Software Inc
10 * Cliff Brake, (c) 2001
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25*/
26
27#include <linux/linkage.h>
28#include <asm/assembler.h>
29#include <asm/hardware.h>
30#include <asm/arch/map.h>
31
32#include <asm/arch/regs-gpio.h>
33#include <asm/arch/regs-clock.h>
34#include <asm/arch/regs-mem.h>
35#include <asm/arch/regs-serial.h>
36
37/* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not
38 * reset the UART configuration, only enable if you really need this!
39*/
40//#define CONFIG_DEBUG_RESUME
41
42 .text
43
44 /* s3c2410_cpu_save
45 *
46 * save enough of the CPU state to allow us to re-start
47 * pm.c code. as we store items like the sp/lr, we will
48 * end up returning from this function when the cpu resumes
49 * so the return value is set to mark this.
50 *
51 * This arangement means we avoid having to flush the cache
52 * from this code.
53 *
54 * entry:
55 * r0 = pointer to save block
56 *
57 * exit:
58 * r0 = 0 => we stored everything
59 * 1 => resumed from sleep
60 */
61
62ENTRY(s3c2410_cpu_save)
63 stmfd sp!, { r4 - r12, lr }
64
65 @@ store co-processor registers
66
67 mrc p15, 0, r4, c13, c0, 0 @ PID
68 mrc p15, 0, r5, c3, c0, 0 @ Domain ID
69 mrc p15, 0, r6, c2, c0, 0 @ translation table base address
70 mrc p15, 0, r7, c1, c0, 0 @ control register
71
72 stmia r0, { r4 - r13 }
73
74 mov r0, #0
75 ldmfd sp, { r4 - r12, pc }
76
77 @@ return to the caller, after having the MMU
78 @@ turned on, this restores the last bits from the
79 @@ stack
80resume_with_mmu:
81 mov r0, #1
82 ldmfd sp!, { r4 - r12, pc }
83
84 .ltorg
85
86 @@ the next bits sit in the .data segment, even though they
87 @@ happen to be code... the s3c2410_sleep_save_phys needs to be
88 @@ accessed by the resume code before it can restore the MMU.
89 @@ This means that the variable has to be close enough for the
90 @@ code to read it... since the .text segment needs to be RO,
91 @@ the data segment can be the only place to put this code.
92
93 .data
94
95 .global s3c2410_sleep_save_phys
96s3c2410_sleep_save_phys:
97 .word 0
98
99 /* s3c2410_cpu_resume
100 *
101 * resume code entry for bootloader to call
102 *
103 * we must put this code here in the data segment as we have no
104 * other way of restoring the stack pointer after sleep, and we
105 * must not write to the code segment (code is read-only)
106 */
107
108ENTRY(s3c2410_cpu_resume)
109 mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
110 msr cpsr_c, r0
111
112 @@ load UART to allow us to print the two characters for
113 @@ resume debug
114
115 mov r2, #S3C24XX_PA_UART & 0xff000000
116 orr r2, r2, #S3C24XX_PA_UART & 0xff000
117
118#if 0
119 /* SMDK2440 LED set */
120 mov r14, #S3C24XX_PA_GPIO
121 ldr r12, [ r14, #0x54 ]
122 bic r12, r12, #3<<4
123 orr r12, r12, #1<<7
124 str r12, [ r14, #0x54 ]
125#endif
126
127#ifdef CONFIG_DEBUG_RESUME
128 mov r3, #'L'
129 strb r3, [ r2, #S3C2410_UTXH ]
1301001:
131 ldrb r14, [ r3, #S3C2410_UTRSTAT ]
132 tst r14, #S3C2410_UTRSTAT_TXE
133 beq 1001b
134#endif /* CONFIG_DEBUG_RESUME */
135
136 mov r1, #0
137 mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
138 mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
139
140 ldr r0, s3c2410_sleep_save_phys @ address of restore block
141 ldmia r0, { r4 - r13 }
142
143 mcr p15, 0, r4, c13, c0, 0 @ PID
144 mcr p15, 0, r5, c3, c0, 0 @ Domain ID
145 mcr p15, 0, r6, c2, c0, 0 @ translation table base
146
147#ifdef CONFIG_DEBUG_RESUME
148 mov r3, #'R'
149 strb r3, [ r2, #S3C2410_UTXH ]
150#endif
151
152 ldr r2, =resume_with_mmu
153 mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, etc
154 nop @ second-to-last before mmu
155 mov pc, r2 @ go back to virtual address
156
157 .ltorg
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/plat-s3c24xx/time.c
index 9910bf0f2cea..c523d1c9cce5 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/plat-s3c24xx/time.c
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/time.c 1/* linux/arch/arm/plat-s3c24xx/time.c
2 * 2 *
3 * Copyright (C) 2003-2005 Simtec Electronics 3 * Copyright (C) 2003-2005 Simtec Electronics
4 * Ben Dooks, <ben@simtec.co.uk> 4 * Ben Dooks, <ben@simtec.co.uk>
@@ -37,8 +37,8 @@
37#include <asm/arch/regs-irq.h> 37#include <asm/arch/regs-irq.h>
38#include <asm/mach/time.h> 38#include <asm/mach/time.h>
39 39
40#include "clock.h" 40#include <asm/plat-s3c24xx/clock.h>
41#include "cpu.h" 41#include <asm/plat-s3c24xx/cpu.h>
42 42
43static unsigned long timer_startval; 43static unsigned long timer_startval;
44static unsigned long timer_usec_ticks; 44static unsigned long timer_usec_ticks;
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 3d0d1097389f..ecbd4a21e432 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2006 Atmel Corporation 4 * Copyright (C) 2006 Atmel Corporation
5 * 5 *
6 * Based on arch/arm/mach-at91rm9200/clock.c 6 * Based on arch/arm/mach-at91/clock.c
7 * Copyright (C) 2005 David Brownell 7 * Copyright (C) 2005 David Brownell
8 * Copyright (C) 2005 Ivan Kokshaysky 8 * Copyright (C) 2005 Ivan Kokshaysky
9 * 9 *
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h
index f953f044ba4d..bb8e1f295835 100644
--- a/arch/avr32/mach-at32ap/clock.h
+++ b/arch/avr32/mach-at32ap/clock.h
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2006 Atmel Corporation 4 * Copyright (C) 2006 Atmel Corporation
5 * 5 *
6 * Based on arch/arm/mach-at91rm9200/clock.c 6 * Based on arch/arm/mach-at91/clock.c
7 * Copyright (C) 2005 David Brownell 7 * Copyright (C) 2005 David Brownell
8 * Copyright (C) 2005 Ivan Kokshaysky 8 * Copyright (C) 2005 Ivan Kokshaysky
9 * 9 *