aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/arm/Samsung-S3C24XX/DMA.txt46
-rw-r--r--Documentation/arm/Samsung-S3C24XX/Overview.txt21
-rw-r--r--arch/arm/Kconfig26
-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/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-ep93xx/clock.c6
-rw-r--r--arch/arm/mach-ep93xx/core.c115
-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/dma.c1546
-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/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/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/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/Kconfig7
-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--drivers/i2c/busses/i2c-pxa.c241
-rw-r--r--drivers/serial/Kconfig3
-rw-r--r--drivers/serial/imx.c14
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c16
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h15
-rw-r--r--include/asm-arm/.gitignore2
-rw-r--r--include/asm-arm/arch-ep93xx/ep93xx-regs.h5
-rw-r--r--include/asm-arm/arch-ep93xx/irqs.h8
-rw-r--r--include/asm-arm/arch-ep93xx/platform.h1
-rw-r--r--include/asm-arm/arch-imx/entry-macro.S18
-rw-r--r--include/asm-arm/arch-ixp4xx/udc.h22
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h24
-rw-r--r--include/asm-arm/arch-pxa/udc.h30
-rw-r--r--include/asm-arm/arch-realview/hardware.h2
-rw-r--r--include/asm-arm/arch-realview/irqs.h5
-rw-r--r--include/asm-arm/arch-realview/platform.h18
-rw-r--r--include/asm-arm/arch-realview/scu.h8
-rw-r--r--include/asm-arm/arch-s3c2410/dma.h36
-rw-r--r--include/asm-arm/arch-s3c2410/irqs.h74
-rw-r--r--include/asm-arm/arch-s3c2410/regs-adc.h2
-rw-r--r--include/asm-arm/arch-s3c2410/regs-gpio.h32
-rw-r--r--include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h194
-rw-r--r--include/asm-arm/arch-s3c2410/regs-serial.h13
-rw-r--r--include/asm-arm/arch-s3c2410/reset.h22
-rw-r--r--include/asm-arm/arch-s3c2410/system.h15
-rw-r--r--include/asm-arm/arch-s3c2410/udc.h36
-rw-r--r--include/asm-arm/cacheflush.h49
-rw-r--r--include/asm-arm/device.h10
-rw-r--r--include/asm-arm/dma-mapping.h18
-rw-r--r--include/asm-arm/domain.h1
-rw-r--r--include/asm-arm/hardware/arm_scu.h2
-rw-r--r--include/asm-arm/hardware/cache-l2x0.h56
-rw-r--r--include/asm-arm/hardware/gic.h5
-rw-r--r--include/asm-arm/hardware/sa1111.h93
-rw-r--r--include/asm-arm/kexec.h30
-rw-r--r--include/asm-arm/pgtable.h54
-rw-r--r--include/asm-arm/plat-s3c24xx/clock.h (renamed from arch/arm/mach-s3c2410/clock.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/common-smdk.h (renamed from arch/arm/mach-s3c2410/common-smdk.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/cpu.h (renamed from arch/arm/mach-s3c2410/cpu.h)3
-rw-r--r--include/asm-arm/plat-s3c24xx/devs.h (renamed from arch/arm/mach-s3c2410/devs.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/dma.h (renamed from arch/arm/mach-s3c2410/dma.h)34
-rw-r--r--include/asm-arm/plat-s3c24xx/irq.h (renamed from arch/arm/mach-s3c2410/irq.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/pm.h (renamed from arch/arm/mach-s3c2410/pm.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2400.h (renamed from arch/arm/mach-s3c2410/s3c2400.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2410.h (renamed from arch/arm/mach-s3c2410/s3c2410.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2412.h (renamed from arch/arm/mach-s3c2410/s3c2412.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2440.h (renamed from arch/arm/mach-s3c2410/s3c2440.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2442.h (renamed from arch/arm/mach-s3c2410/s3c2442.h)2
-rw-r--r--include/asm-arm/plat-s3c24xx/s3c2443.h32
-rw-r--r--include/asm-arm/system.h62
-rw-r--r--include/asm-arm/tlbflush.h50
-rw-r--r--include/asm-arm/unistd.h1
-rw-r--r--include/linux/kexec.h1
163 files changed, 9162 insertions, 5251 deletions
diff --git a/Documentation/arm/Samsung-S3C24XX/DMA.txt b/Documentation/arm/Samsung-S3C24XX/DMA.txt
new file mode 100644
index 000000000000..37f4edcc5d87
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/DMA.txt
@@ -0,0 +1,46 @@
1 S3C2410 DMA
2 ===========
3
4Introduction
5------------
6
7 The kernel provides an interface to manage DMA transfers
8 using the DMA channels in the cpu, so that the central
9 duty of managing channel mappings, and programming the
10 channel generators is in one place.
11
12
13DMA Channel Ordering
14--------------------
15
16 Many of the range do not have connections for the DMA
17 channels to all sources, which means that some devices
18 have a restricted number of channels that can be used.
19
20 To allow flexibilty for each cpu type and board, the
21 dma code can be given an dma ordering structure which
22 allows the order of channel search to be specified, as
23 well as allowing the prohibition of certain claims.
24
25 struct s3c24xx_dma_order has a list of channels, and
26 each channel within has a slot for a list of dma
27 channel numbers. The slots are searched in order, for
28 the presence of a dma channel number with DMA_CH_VALID
29 orred in.
30
31 If the order has the flag DMA_CH_NEVER set, then after
32 checking the channel list, the system will return no
33 found channel, thus denying the request.
34
35 A board support file can call s3c24xx_dma_order_set()
36 to register an complete ordering set. The routine will
37 copy the data, so the original can be discared with
38 __initdata.
39
40
41Authour
42-------
43
44Ben Dooks,
45Copyright (c) 2007 Ben Dooks, Simtec Electronics
46Licensed under the GPL v2
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index 28d014714ab8..c31b76fa66c4 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -8,13 +8,10 @@ Introduction
8 8
9 The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported 9 The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
10 by the 's3c2410' architecture of ARM Linux. Currently the S3C2410, 10 by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
11 S3C2440 and S3C2442 devices are supported. 11 S3C2412, S3C2413, S3C2440 and S3C2442 devices are supported.
12 12
13 Support for the S3C2400 series is in progress. 13 Support for the S3C2400 series is in progress.
14 14
15 Support for the S3C2412 and S3C2413 CPUs is being merged.
16
17
18Configuration 15Configuration
19------------- 16-------------
20 17
@@ -26,6 +23,22 @@ Configuration
26 please check the machine specific documentation. 23 please check the machine specific documentation.
27 24
28 25
26Layout
27------
28
29 The core support files are located in the platform code contained in
30 arch/arm/plat-s3c24xx with headers in include/asm-arm/plat-s3c24xx.
31 This directory should be kept to items shared between the platform
32 code (arch/arm/plat-s3c24xx) and the arch/arm/mach-s3c24* code.
33
34 Each cpu has a directory with the support files for it, and the
35 machines that carry the device. For example S3C2410 is contained
36 in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
37
38 Register, kernel and platform data definitions are held in the
39 include/asm-arm/arch-s3c2410 directory.
40
41
29Machines 42Machines
30-------- 43--------
31 44
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9c7565c8f376..195650935c78 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -280,6 +280,7 @@ config ARCH_PXA
280 bool "PXA2xx-based" 280 bool "PXA2xx-based"
281 depends on MMU 281 depends on MMU
282 select ARCH_MTD_XIP 282 select ARCH_MTD_XIP
283 select GENERIC_TIME
283 help 284 help
284 Support for Intel's PXA2XX processor line. 285 Support for Intel's PXA2XX processor line.
285 286
@@ -303,7 +304,7 @@ config ARCH_SA1100
303 Support for StrongARM 11x0 based boards. 304 Support for StrongARM 11x0 based boards.
304 305
305config ARCH_S3C2410 306config ARCH_S3C2410
306 bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442" 307 bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
307 help 308 help
308 Samsung S3C2410X CPU based systems, such as the Simtec Electronics 309 Samsung S3C2410X CPU based systems, such as the Simtec Electronics
309 BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or 310 BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -363,7 +364,16 @@ source "arch/arm/mach-omap1/Kconfig"
363 364
364source "arch/arm/mach-omap2/Kconfig" 365source "arch/arm/mach-omap2/Kconfig"
365 366
367source "arch/arm/plat-s3c24xx/Kconfig"
368
369if ARCH_S3C2410
370source "arch/arm/mach-s3c2400/Kconfig"
366source "arch/arm/mach-s3c2410/Kconfig" 371source "arch/arm/mach-s3c2410/Kconfig"
372source "arch/arm/mach-s3c2412/Kconfig"
373source "arch/arm/mach-s3c2440/Kconfig"
374source "arch/arm/mach-s3c2442/Kconfig"
375source "arch/arm/mach-s3c2443/Kconfig"
376endif
367 377
368source "arch/arm/mach-lh7a40x/Kconfig" 378source "arch/arm/mach-lh7a40x/Kconfig"
369 379
@@ -738,6 +748,20 @@ config XIP_PHYS_ADDR
738 be linked for and stored to. This address is dependent on your 748 be linked for and stored to. This address is dependent on your
739 own flash usage. 749 own flash usage.
740 750
751config KEXEC
752 bool "Kexec system call (EXPERIMENTAL)"
753 depends on EXPERIMENTAL
754 help
755 kexec is a system call that implements the ability to shutdown your
756 current kernel, and to start another kernel. It is like a reboot
757 but it is indepedent of the system firmware. And like a reboot
758 you can start any kernel with it, not just Linux.
759
760 It is an ongoing process to be certain the hardware in a machine
761 is properly shutdown, so do not be surprised if this code does not
762 initially work for you. It may help to enable device hotplugging
763 support.
764
741endmenu 765endmenu
742 766
743if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX ) 767if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 0205547fa45c..2cd871c82c96 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -149,7 +149,7 @@ MACHINE := arch/arm/mach-$(machine-y)/
149else 149else
150MACHINE := 150MACHINE :=
151endif 151endif
152 152
153export TEXT_OFFSET GZFLAGS MMUEXT 153export TEXT_OFFSET GZFLAGS MMUEXT
154 154
155# Do we have FASTFPE? 155# Do we have FASTFPE?
@@ -161,6 +161,11 @@ endif
161# If we have a machine-specific directory, then include it in the build. 161# If we have a machine-specific directory, then include it in the build.
162core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ 162core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
163core-y += $(MACHINE) 163core-y += $(MACHINE)
164core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2400/
165core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2412/
166core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2440/
167core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2442/
168core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2443/
164core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ 169core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
165core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) 170core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
166core-$(CONFIG_VFP) += arch/arm/vfp/ 171core-$(CONFIG_VFP) += arch/arm/vfp/
@@ -168,6 +173,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/
168# If we have a common platform directory, then include it in the build. 173# If we have a common platform directory, then include it in the build.
169core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/ 174core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/
170core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/ 175core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/
176core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/
171 177
172drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ 178drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
173drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ 179drivers-$(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/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-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-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/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/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/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/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/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 b305cbda8b87..da8f043dc2cc 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -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/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index c3b1567c852a..14e83d0aac8c 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -34,6 +34,7 @@
34 34
35#include <asm/hardware.h> 35#include <asm/hardware.h>
36#include <asm/irq.h> 36#include <asm/irq.h>
37#include <asm/io.h>
37#include <asm/arch/i2c.h> 38#include <asm/arch/i2c.h>
38#include <asm/arch/pxa-regs.h> 39#include <asm/arch/pxa-regs.h>
39 40
@@ -54,8 +55,21 @@ struct pxa_i2c {
54 unsigned int irqlogidx; 55 unsigned int irqlogidx;
55 u32 isrlog[32]; 56 u32 isrlog[32];
56 u32 icrlog[32]; 57 u32 icrlog[32];
58
59 void __iomem *reg_base;
60
61 unsigned long iobase;
62 unsigned long iosize;
63
64 int irq;
57}; 65};
58 66
67#define _IBMR(i2c) ((i2c)->reg_base + 0)
68#define _IDBR(i2c) ((i2c)->reg_base + 8)
69#define _ICR(i2c) ((i2c)->reg_base + 0x10)
70#define _ISR(i2c) ((i2c)->reg_base + 0x18)
71#define _ISAR(i2c) ((i2c)->reg_base + 0x20)
72
59/* 73/*
60 * I2C Slave mode address 74 * I2C Slave mode address
61 */ 75 */
@@ -130,7 +144,8 @@ static unsigned int i2c_debug = DEBUG;
130 144
131static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname) 145static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
132{ 146{
133 dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR); 147 dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno,
148 readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
134} 149}
135 150
136#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__) 151#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
@@ -153,7 +168,7 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
153 printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n", 168 printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
154 i2c->msg_num, i2c->msg_idx, i2c->msg_ptr); 169 i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
155 printk("i2c: ICR: %08x ISR: %08x\n" 170 printk("i2c: ICR: %08x ISR: %08x\n"
156 "i2c: log: ", ICR, ISR); 171 "i2c: log: ", readl(_ICR(i2c)), readl(_ISR(i2c)));
157 for (i = 0; i < i2c->irqlogidx; i++) 172 for (i = 0; i < i2c->irqlogidx; i++)
158 printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]); 173 printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
159 printk("\n"); 174 printk("\n");
@@ -161,7 +176,7 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
161 176
162static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) 177static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c)
163{ 178{
164 return !(ICR & ICR_SCLE); 179 return !(readl(_ICR(i2c)) & ICR_SCLE);
165} 180}
166 181
167static void i2c_pxa_abort(struct pxa_i2c *i2c) 182static void i2c_pxa_abort(struct pxa_i2c *i2c)
@@ -173,28 +188,29 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c)
173 return; 188 return;
174 } 189 }
175 190
176 while (time_before(jiffies, timeout) && (IBMR & 0x1) == 0) { 191 while (time_before(jiffies, timeout) && (readl(_IBMR(i2c)) & 0x1) == 0) {
177 unsigned long icr = ICR; 192 unsigned long icr = readl(_ICR(i2c));
178 193
179 icr &= ~ICR_START; 194 icr &= ~ICR_START;
180 icr |= ICR_ACKNAK | ICR_STOP | ICR_TB; 195 icr |= ICR_ACKNAK | ICR_STOP | ICR_TB;
181 196
182 ICR = icr; 197 writel(icr, _ICR(i2c));
183 198
184 show_state(i2c); 199 show_state(i2c);
185 200
186 msleep(1); 201 msleep(1);
187 } 202 }
188 203
189 ICR &= ~(ICR_MA | ICR_START | ICR_STOP); 204 writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP),
205 _ICR(i2c));
190} 206}
191 207
192static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) 208static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c)
193{ 209{
194 int timeout = DEF_TIMEOUT; 210 int timeout = DEF_TIMEOUT;
195 211
196 while (timeout-- && ISR & (ISR_IBB | ISR_UB)) { 212 while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
197 if ((ISR & ISR_SAD) != 0) 213 if ((readl(_ISR(i2c)) & ISR_SAD) != 0)
198 timeout += 4; 214 timeout += 4;
199 215
200 msleep(2); 216 msleep(2);
@@ -214,9 +230,9 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
214 while (time_before(jiffies, timeout)) { 230 while (time_before(jiffies, timeout)) {
215 if (i2c_debug > 1) 231 if (i2c_debug > 1)
216 dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", 232 dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
217 __func__, (long)jiffies, ISR, ICR, IBMR); 233 __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
218 234
219 if (ISR & ISR_SAD) { 235 if (readl(_ISR(i2c)) & ISR_SAD) {
220 if (i2c_debug > 0) 236 if (i2c_debug > 0)
221 dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__); 237 dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__);
222 goto out; 238 goto out;
@@ -226,7 +242,7 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c)
226 * quick check of the i2c lines themselves to ensure they've 242 * quick check of the i2c lines themselves to ensure they've
227 * gone high... 243 * gone high...
228 */ 244 */
229 if ((ISR & (ISR_UB | ISR_IBB)) == 0 && IBMR == 3) { 245 if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && readl(_IBMR(i2c)) == 3) {
230 if (i2c_debug > 0) 246 if (i2c_debug > 0)
231 dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); 247 dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
232 return 1; 248 return 1;
@@ -246,7 +262,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c)
246 if (i2c_debug) 262 if (i2c_debug)
247 dev_dbg(&i2c->adap.dev, "setting to bus master\n"); 263 dev_dbg(&i2c->adap.dev, "setting to bus master\n");
248 264
249 if ((ISR & (ISR_UB | ISR_IBB)) != 0) { 265 if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) {
250 dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__); 266 dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__);
251 if (!i2c_pxa_wait_master(i2c)) { 267 if (!i2c_pxa_wait_master(i2c)) {
252 dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__); 268 dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__);
@@ -254,7 +270,7 @@ static int i2c_pxa_set_master(struct pxa_i2c *i2c)
254 } 270 }
255 } 271 }
256 272
257 ICR |= ICR_SCLE; 273 writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
258 return 0; 274 return 0;
259} 275}
260 276
@@ -270,11 +286,11 @@ static int i2c_pxa_wait_slave(struct pxa_i2c *i2c)
270 while (time_before(jiffies, timeout)) { 286 while (time_before(jiffies, timeout)) {
271 if (i2c_debug > 1) 287 if (i2c_debug > 1)
272 dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", 288 dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n",
273 __func__, (long)jiffies, ISR, ICR, IBMR); 289 __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
274 290
275 if ((ISR & (ISR_UB|ISR_IBB)) == 0 || 291 if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 ||
276 (ISR & ISR_SAD) != 0 || 292 (readl(_ISR(i2c)) & ISR_SAD) != 0 ||
277 (ICR & ICR_SCLE) == 0) { 293 (readl(_ICR(i2c)) & ICR_SCLE) == 0) {
278 if (i2c_debug > 1) 294 if (i2c_debug > 1)
279 dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); 295 dev_dbg(&i2c->adap.dev, "%s: done\n", __func__);
280 return 1; 296 return 1;
@@ -302,9 +318,9 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
302 /* we need to wait for the stop condition to end */ 318 /* we need to wait for the stop condition to end */
303 319
304 /* if we where in stop, then clear... */ 320 /* if we where in stop, then clear... */
305 if (ICR & ICR_STOP) { 321 if (readl(_ICR(i2c)) & ICR_STOP) {
306 udelay(100); 322 udelay(100);
307 ICR &= ~ICR_STOP; 323 writel(readl(_ICR(i2c)) & ~ICR_STOP, _ICR(i2c));
308 } 324 }
309 325
310 if (!i2c_pxa_wait_slave(i2c)) { 326 if (!i2c_pxa_wait_slave(i2c)) {
@@ -314,12 +330,12 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode)
314 } 330 }
315 } 331 }
316 332
317 ICR &= ~(ICR_STOP|ICR_ACKNAK|ICR_MA); 333 writel(readl(_ICR(i2c)) & ~(ICR_STOP|ICR_ACKNAK|ICR_MA), _ICR(i2c));
318 ICR &= ~ICR_SCLE; 334 writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
319 335
320 if (i2c_debug) { 336 if (i2c_debug) {
321 dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", ICR, ISR); 337 dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", readl(_ICR(i2c)), readl(_ISR(i2c)));
322 decode_ICR(ICR); 338 decode_ICR(readl(_ICR(i2c)));
323 } 339 }
324} 340}
325#else 341#else
@@ -334,24 +350,24 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
334 i2c_pxa_abort(i2c); 350 i2c_pxa_abort(i2c);
335 351
336 /* reset according to 9.8 */ 352 /* reset according to 9.8 */
337 ICR = ICR_UR; 353 writel(ICR_UR, _ICR(i2c));
338 ISR = I2C_ISR_INIT; 354 writel(I2C_ISR_INIT, _ISR(i2c));
339 ICR &= ~ICR_UR; 355 writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
340 356
341 ISAR = i2c->slave_addr; 357 writel(i2c->slave_addr, _ISAR(i2c));
342 358
343 /* set control register values */ 359 /* set control register values */
344 ICR = I2C_ICR_INIT; 360 writel(I2C_ICR_INIT, _ICR(i2c));
345 361
346#ifdef CONFIG_I2C_PXA_SLAVE 362#ifdef CONFIG_I2C_PXA_SLAVE
347 dev_info(&i2c->adap.dev, "Enabling slave mode\n"); 363 dev_info(&i2c->adap.dev, "Enabling slave mode\n");
348 ICR |= ICR_SADIE | ICR_ALDIE | ICR_SSDIE; 364 writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c));
349#endif 365#endif
350 366
351 i2c_pxa_set_slave(i2c, 0); 367 i2c_pxa_set_slave(i2c, 0);
352 368
353 /* enable unit */ 369 /* enable unit */
354 ICR |= ICR_IUE; 370 writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c));
355 udelay(100); 371 udelay(100);
356} 372}
357 373
@@ -371,19 +387,19 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
371 if (i2c->slave != NULL) 387 if (i2c->slave != NULL)
372 ret = i2c->slave->read(i2c->slave->data); 388 ret = i2c->slave->read(i2c->slave->data);
373 389
374 IDBR = ret; 390 writel(ret, _IDBR(i2c));
375 ICR |= ICR_TB; /* allow next byte */ 391 writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); /* allow next byte */
376 } 392 }
377} 393}
378 394
379static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) 395static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
380{ 396{
381 unsigned int byte = IDBR; 397 unsigned int byte = readl(_IDBR(i2c));
382 398
383 if (i2c->slave != NULL) 399 if (i2c->slave != NULL)
384 i2c->slave->write(i2c->slave->data, byte); 400 i2c->slave->write(i2c->slave->data, byte);
385 401
386 ICR |= ICR_TB; 402 writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
387} 403}
388 404
389static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) 405static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -403,13 +419,13 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
403 * start condition... if this happens, we'd better back off 419 * start condition... if this happens, we'd better back off
404 * and stop holding the poor thing up 420 * and stop holding the poor thing up
405 */ 421 */
406 ICR &= ~(ICR_START|ICR_STOP); 422 writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
407 ICR |= ICR_TB; 423 writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
408 424
409 timeout = 0x10000; 425 timeout = 0x10000;
410 426
411 while (1) { 427 while (1) {
412 if ((IBMR & 2) == 2) 428 if ((readl(_IBMR(i2c)) & 2) == 2)
413 break; 429 break;
414 430
415 timeout--; 431 timeout--;
@@ -420,7 +436,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
420 } 436 }
421 } 437 }
422 438
423 ICR &= ~ICR_SCLE; 439 writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
424} 440}
425 441
426static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) 442static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -447,14 +463,14 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr)
447 if (isr & ISR_BED) { 463 if (isr & ISR_BED) {
448 /* what should we do here? */ 464 /* what should we do here? */
449 } else { 465 } else {
450 IDBR = 0; 466 writel(0, _IDBR(i2c));
451 ICR |= ICR_TB; 467 writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));
452 } 468 }
453} 469}
454 470
455static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) 471static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr)
456{ 472{
457 ICR |= ICR_TB | ICR_ACKNAK; 473 writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
458} 474}
459 475
460static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) 476static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
@@ -466,13 +482,13 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
466 * start condition... if this happens, we'd better back off 482 * start condition... if this happens, we'd better back off
467 * and stop holding the poor thing up 483 * and stop holding the poor thing up
468 */ 484 */
469 ICR &= ~(ICR_START|ICR_STOP); 485 writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c));
470 ICR |= ICR_TB | ICR_ACKNAK; 486 writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c));
471 487
472 timeout = 0x10000; 488 timeout = 0x10000;
473 489
474 while (1) { 490 while (1) {
475 if ((IBMR & 2) == 2) 491 if ((readl(_IBMR(i2c)) & 2) == 2)
476 break; 492 break;
477 493
478 timeout--; 494 timeout--;
@@ -483,7 +499,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr)
483 } 499 }
484 } 500 }
485 501
486 ICR &= ~ICR_SCLE; 502 writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c));
487} 503}
488 504
489static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) 505static void i2c_pxa_slave_stop(struct pxa_i2c *i2c)
@@ -514,13 +530,13 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
514 /* 530 /*
515 * Step 1: target slave address into IDBR 531 * Step 1: target slave address into IDBR
516 */ 532 */
517 IDBR = i2c_pxa_addr_byte(i2c->msg); 533 writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
518 534
519 /* 535 /*
520 * Step 2: initiate the write. 536 * Step 2: initiate the write.
521 */ 537 */
522 icr = ICR & ~(ICR_STOP | ICR_ALDIE); 538 icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE);
523 ICR = icr | ICR_START | ICR_TB; 539 writel(icr | ICR_START | ICR_TB, _ICR(i2c));
524} 540}
525 541
526/* 542/*
@@ -594,7 +610,7 @@ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
594 610
595static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) 611static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
596{ 612{
597 u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); 613 u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
598 614
599 again: 615 again:
600 /* 616 /*
@@ -645,7 +661,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
645 /* 661 /*
646 * Write mode. Write the next data byte. 662 * Write mode. Write the next data byte.
647 */ 663 */
648 IDBR = i2c->msg->buf[i2c->msg_ptr++]; 664 writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c));
649 665
650 icr |= ICR_ALDIE | ICR_TB; 666 icr |= ICR_ALDIE | ICR_TB;
651 667
@@ -675,7 +691,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
675 /* 691 /*
676 * Write the next address. 692 * Write the next address.
677 */ 693 */
678 IDBR = i2c_pxa_addr_byte(i2c->msg); 694 writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c));
679 695
680 /* 696 /*
681 * And trigger a repeated start, and send the byte. 697 * And trigger a repeated start, and send the byte.
@@ -696,18 +712,18 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
696 712
697 i2c->icrlog[i2c->irqlogidx-1] = icr; 713 i2c->icrlog[i2c->irqlogidx-1] = icr;
698 714
699 ICR = icr; 715 writel(icr, _ICR(i2c));
700 show_state(i2c); 716 show_state(i2c);
701} 717}
702 718
703static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr) 719static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
704{ 720{
705 u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); 721 u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB);
706 722
707 /* 723 /*
708 * Read the byte. 724 * Read the byte.
709 */ 725 */
710 i2c->msg->buf[i2c->msg_ptr++] = IDBR; 726 i2c->msg->buf[i2c->msg_ptr++] = readl(_IDBR(i2c));
711 727
712 if (i2c->msg_ptr < i2c->msg->len) { 728 if (i2c->msg_ptr < i2c->msg->len) {
713 /* 729 /*
@@ -724,17 +740,17 @@ static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
724 740
725 i2c->icrlog[i2c->irqlogidx-1] = icr; 741 i2c->icrlog[i2c->irqlogidx-1] = icr;
726 742
727 ICR = icr; 743 writel(icr, _ICR(i2c));
728} 744}
729 745
730static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id) 746static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
731{ 747{
732 struct pxa_i2c *i2c = dev_id; 748 struct pxa_i2c *i2c = dev_id;
733 u32 isr = ISR; 749 u32 isr = readl(_ISR(i2c));
734 750
735 if (i2c_debug > 2 && 0) { 751 if (i2c_debug > 2 && 0) {
736 dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n", 752 dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
737 __func__, isr, ICR, IBMR); 753 __func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
738 decode_ISR(isr); 754 decode_ISR(isr);
739 } 755 }
740 756
@@ -746,7 +762,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
746 /* 762 /*
747 * Always clear all pending IRQs. 763 * Always clear all pending IRQs.
748 */ 764 */
749 ISR = isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED); 765 writel(isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED), _ISR(i2c));
750 766
751 if (isr & ISR_SAD) 767 if (isr & ISR_SAD)
752 i2c_pxa_slave_start(i2c, isr); 768 i2c_pxa_slave_start(i2c, isr);
@@ -779,7 +795,7 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num
779 /* If the I2C controller is disabled we need to reset it (probably due 795 /* If the I2C controller is disabled we need to reset it (probably due
780 to a suspend/resume destroying state). We do this here as we can then 796 to a suspend/resume destroying state). We do this here as we can then
781 avoid worrying about resuming the controller before its users. */ 797 avoid worrying about resuming the controller before its users. */
782 if (!(ICR & ICR_IUE)) 798 if (!(readl(_ICR(i2c)) & ICR_IUE))
783 i2c_pxa_reset(i2c); 799 i2c_pxa_reset(i2c);
784 800
785 for (i = adap->retries; i >= 0; i--) { 801 for (i = adap->retries; i >= 0; i--) {
@@ -810,28 +826,53 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
810 826
811static struct pxa_i2c i2c_pxa = { 827static struct pxa_i2c i2c_pxa = {
812 .lock = SPIN_LOCK_UNLOCKED, 828 .lock = SPIN_LOCK_UNLOCKED,
813 .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
814 .adap = { 829 .adap = {
815 .owner = THIS_MODULE, 830 .owner = THIS_MODULE,
816 .algo = &i2c_pxa_algorithm, 831 .algo = &i2c_pxa_algorithm,
817 .name = "pxa2xx-i2c", 832 .name = "pxa2xx-i2c.0",
818 .retries = 5, 833 .retries = 5,
819 }, 834 },
820}; 835};
821 836
837#define res_len(r) ((r)->end - (r)->start + 1)
822static int i2c_pxa_probe(struct platform_device *dev) 838static int i2c_pxa_probe(struct platform_device *dev)
823{ 839{
824 struct pxa_i2c *i2c = &i2c_pxa; 840 struct pxa_i2c *i2c = &i2c_pxa;
841 struct resource *res;
825#ifdef CONFIG_I2C_PXA_SLAVE 842#ifdef CONFIG_I2C_PXA_SLAVE
826 struct i2c_pxa_platform_data *plat = dev->dev.platform_data; 843 struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
827#endif 844#endif
828 int ret; 845 int ret;
846 int irq;
829 847
830#ifdef CONFIG_PXA27x 848 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
831 pxa_gpio_mode(GPIO117_I2CSCL_MD); 849 irq = platform_get_irq(dev, 0);
832 pxa_gpio_mode(GPIO118_I2CSDA_MD); 850 if (res == NULL || irq < 0)
833 udelay(100); 851 return -ENODEV;
834#endif 852
853 if (!request_mem_region(res->start, res_len(res), res->name))
854 return -ENOMEM;
855
856 i2c = kmalloc(sizeof(struct pxa_i2c), GFP_KERNEL);
857 if (!i2c) {
858 ret = -ENOMEM;
859 goto emalloc;
860 }
861
862 memcpy(i2c, &i2c_pxa, sizeof(struct pxa_i2c));
863 init_waitqueue_head(&i2c->wait);
864 i2c->adap.name[strlen(i2c->adap.name) - 1] = '0' + dev->id % 10;
865
866 i2c->reg_base = ioremap(res->start, res_len(res));
867 if (!i2c->reg_base) {
868 ret = -EIO;
869 goto eremap;
870 }
871
872 i2c->iobase = res->start;
873 i2c->iosize = res_len(res);
874
875 i2c->irq = irq;
835 876
836 i2c->slave_addr = I2C_PXA_SLAVE_ADDR; 877 i2c->slave_addr = I2C_PXA_SLAVE_ADDR;
837 878
@@ -842,11 +883,28 @@ static int i2c_pxa_probe(struct platform_device *dev)
842 } 883 }
843#endif 884#endif
844 885
845 pxa_set_cken(CKEN14_I2C, 1); 886 switch (dev->id) {
846 ret = request_irq(IRQ_I2C, i2c_pxa_handler, IRQF_DISABLED, 887 case 0:
847 "pxa2xx-i2c", i2c); 888#ifdef CONFIG_PXA27x
889 pxa_gpio_mode(GPIO117_I2CSCL_MD);
890 pxa_gpio_mode(GPIO118_I2CSDA_MD);
891#endif
892 pxa_set_cken(CKEN14_I2C, 1);
893 break;
894#ifdef CONFIG_PXA27x
895 case 1:
896 local_irq_disable();
897 PCFR |= PCFR_PI2CEN;
898 local_irq_enable();
899 pxa_set_cken(CKEN15_PWRI2C, 1);
900#endif
901 }
902
903 ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
904 i2c->adap.name, i2c);
848 if (ret) 905 if (ret)
849 goto out; 906 goto ereqirq;
907
850 908
851 i2c_pxa_reset(i2c); 909 i2c_pxa_reset(i2c);
852 910
@@ -856,7 +914,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
856 ret = i2c_add_adapter(&i2c->adap); 914 ret = i2c_add_adapter(&i2c->adap);
857 if (ret < 0) { 915 if (ret < 0) {
858 printk(KERN_INFO "I2C: Failed to add bus\n"); 916 printk(KERN_INFO "I2C: Failed to add bus\n");
859 goto err_irq; 917 goto eadapt;
860 } 918 }
861 919
862 platform_set_drvdata(dev, i2c); 920 platform_set_drvdata(dev, i2c);
@@ -870,9 +928,25 @@ static int i2c_pxa_probe(struct platform_device *dev)
870#endif 928#endif
871 return 0; 929 return 0;
872 930
873 err_irq: 931eadapt:
874 free_irq(IRQ_I2C, i2c); 932 free_irq(irq, i2c);
875 out: 933ereqirq:
934 switch (dev->id) {
935 case 0:
936 pxa_set_cken(CKEN14_I2C, 0);
937 break;
938#ifdef CONFIG_PXA27x
939 case 1:
940 pxa_set_cken(CKEN15_PWRI2C, 0);
941 local_irq_disable();
942 PCFR &= ~PCFR_PI2CEN;
943 local_irq_enable();
944#endif
945 }
946eremap:
947 kfree(i2c);
948emalloc:
949 release_mem_region(res->start, res_len(res));
876 return ret; 950 return ret;
877} 951}
878 952
@@ -883,8 +957,21 @@ static int i2c_pxa_remove(struct platform_device *dev)
883 platform_set_drvdata(dev, NULL); 957 platform_set_drvdata(dev, NULL);
884 958
885 i2c_del_adapter(&i2c->adap); 959 i2c_del_adapter(&i2c->adap);
886 free_irq(IRQ_I2C, i2c); 960 free_irq(i2c->irq, i2c);
887 pxa_set_cken(CKEN14_I2C, 0); 961 switch (dev->id) {
962 case 0:
963 pxa_set_cken(CKEN14_I2C, 0);
964 break;
965#ifdef CONFIG_PXA27x
966 case 1:
967 pxa_set_cken(CKEN15_PWRI2C, 0);
968 local_irq_disable();
969 PCFR &= ~PCFR_PI2CEN;
970 local_irq_enable();
971#endif
972 }
973 release_mem_region(i2c->iobase, i2c->iosize);
974 kfree(i2c);
888 975
889 return 0; 976 return 0;
890} 977}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 2978c09860ee..09f8bff1fbd1 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -262,7 +262,8 @@ config SERIAL_AMBA_PL010
262 select SERIAL_CORE 262 select SERIAL_CORE
263 help 263 help
264 This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have 264 This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
265 an Integrator/AP or Integrator/PP2 platform, say Y or M here. 265 an Integrator/AP or Integrator/PP2 platform, or if you have a
266 Cirrus Logic EP93xx CPU, say Y or M here.
266 267
267 If unsure, say N. 268 If unsure, say N.
268 269
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index e216dcf29376..04cc88cc528c 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -154,7 +154,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
154{ 154{
155 struct circ_buf *xmit = &sport->port.info->xmit; 155 struct circ_buf *xmit = &sport->port.info->xmit;
156 156
157 do { 157 while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)) {
158 /* send xmit->buf[xmit->tail] 158 /* send xmit->buf[xmit->tail]
159 * out the port here */ 159 * out the port here */
160 URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail]; 160 URTX0((u32)sport->port.membase) = xmit->buf[xmit->tail];
@@ -163,7 +163,7 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
163 sport->port.icount.tx++; 163 sport->port.icount.tx++;
164 if (uart_circ_empty(xmit)) 164 if (uart_circ_empty(xmit))
165 break; 165 break;
166 } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)); 166 }
167 167
168 if (uart_circ_empty(xmit)) 168 if (uart_circ_empty(xmit))
169 imx_stop_tx(&sport->port); 169 imx_stop_tx(&sport->port);
@@ -178,8 +178,7 @@ static void imx_start_tx(struct uart_port *port)
178 178
179 UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN; 179 UCR1((u32)sport->port.membase) |= UCR1_TXMPTYEN;
180 180
181 if(UTS((u32)sport->port.membase) & UTS_TXEMPTY) 181 imx_transmit_buffer(sport);
182 imx_transmit_buffer(sport);
183} 182}
184 183
185static irqreturn_t imx_rtsint(int irq, void *dev_id) 184static irqreturn_t imx_rtsint(int irq, void *dev_id)
@@ -404,7 +403,8 @@ static int imx_startup(struct uart_port *port)
404 if (retval) goto error_out2; 403 if (retval) goto error_out2;
405 404
406 retval = request_irq(sport->rtsirq, imx_rtsint, 405 retval = request_irq(sport->rtsirq, imx_rtsint,
407 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, 406 (sport->rtsirq < IMX_IRQS) ? 0 :
407 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
408 DRIVER_NAME, sport); 408 DRIVER_NAME, sport);
409 if (retval) goto error_out3; 409 if (retval) goto error_out3;
410 410
@@ -678,7 +678,7 @@ static struct imx_port imx_ports[] = {
678 .mapbase = IMX_UART1_BASE, /* FIXME */ 678 .mapbase = IMX_UART1_BASE, /* FIXME */
679 .irq = UART1_MINT_RX, 679 .irq = UART1_MINT_RX,
680 .uartclk = 16000000, 680 .uartclk = 16000000,
681 .fifosize = 8, 681 .fifosize = 32,
682 .flags = UPF_BOOT_AUTOCONF, 682 .flags = UPF_BOOT_AUTOCONF,
683 .ops = &imx_pops, 683 .ops = &imx_pops,
684 .line = 0, 684 .line = 0,
@@ -694,7 +694,7 @@ static struct imx_port imx_ports[] = {
694 .mapbase = IMX_UART2_BASE, /* FIXME */ 694 .mapbase = IMX_UART2_BASE, /* FIXME */
695 .irq = UART2_MINT_RX, 695 .irq = UART2_MINT_RX,
696 .uartclk = 16000000, 696 .uartclk = 16000000,
697 .fifosize = 8, 697 .fifosize = 32,
698 .flags = UPF_BOOT_AUTOCONF, 698 .flags = UPF_BOOT_AUTOCONF,
699 .ops = &imx_pops, 699 .ops = &imx_pops,
700 .line = 1, 700 .line = 1,
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index b78de9694665..3547f049237e 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -156,7 +156,7 @@ static int is_vbus_present(void)
156 struct pxa2xx_udc_mach_info *mach = the_controller->mach; 156 struct pxa2xx_udc_mach_info *mach = the_controller->mach;
157 157
158 if (mach->gpio_vbus) 158 if (mach->gpio_vbus)
159 return pxa_gpio_get(mach->gpio_vbus); 159 return udc_gpio_get(mach->gpio_vbus);
160 if (mach->udc_is_connected) 160 if (mach->udc_is_connected)
161 return mach->udc_is_connected(); 161 return mach->udc_is_connected();
162 return 1; 162 return 1;
@@ -168,7 +168,7 @@ static void pullup_off(void)
168 struct pxa2xx_udc_mach_info *mach = the_controller->mach; 168 struct pxa2xx_udc_mach_info *mach = the_controller->mach;
169 169
170 if (mach->gpio_pullup) 170 if (mach->gpio_pullup)
171 pxa_gpio_set(mach->gpio_pullup, 0); 171 udc_gpio_set(mach->gpio_pullup, 0);
172 else if (mach->udc_command) 172 else if (mach->udc_command)
173 mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); 173 mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
174} 174}
@@ -178,7 +178,7 @@ static void pullup_on(void)
178 struct pxa2xx_udc_mach_info *mach = the_controller->mach; 178 struct pxa2xx_udc_mach_info *mach = the_controller->mach;
179 179
180 if (mach->gpio_pullup) 180 if (mach->gpio_pullup)
181 pxa_gpio_set(mach->gpio_pullup, 1); 181 udc_gpio_set(mach->gpio_pullup, 1);
182 else if (mach->udc_command) 182 else if (mach->udc_command)
183 mach->udc_command(PXA2XX_UDC_CMD_CONNECT); 183 mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
184} 184}
@@ -1756,7 +1756,7 @@ lubbock_vbus_irq(int irq, void *_dev)
1756static irqreturn_t udc_vbus_irq(int irq, void *_dev) 1756static irqreturn_t udc_vbus_irq(int irq, void *_dev)
1757{ 1757{
1758 struct pxa2xx_udc *dev = _dev; 1758 struct pxa2xx_udc *dev = _dev;
1759 int vbus = pxa_gpio_get(dev->mach->gpio_vbus); 1759 int vbus = udc_gpio_get(dev->mach->gpio_vbus);
1760 1760
1761 pxa2xx_udc_vbus_session(&dev->gadget, vbus); 1761 pxa2xx_udc_vbus_session(&dev->gadget, vbus);
1762 return IRQ_HANDLED; 1762 return IRQ_HANDLED;
@@ -2546,15 +2546,13 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
2546 dev->dev = &pdev->dev; 2546 dev->dev = &pdev->dev;
2547 dev->mach = pdev->dev.platform_data; 2547 dev->mach = pdev->dev.platform_data;
2548 if (dev->mach->gpio_vbus) { 2548 if (dev->mach->gpio_vbus) {
2549 vbus_irq = IRQ_GPIO(dev->mach->gpio_vbus & GPIO_MD_MASK_NR); 2549 udc_gpio_init_vbus(dev->mach->gpio_vbus);
2550 pxa_gpio_mode((dev->mach->gpio_vbus & GPIO_MD_MASK_NR) 2550 vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
2551 | GPIO_IN);
2552 set_irq_type(vbus_irq, IRQT_BOTHEDGE); 2551 set_irq_type(vbus_irq, IRQT_BOTHEDGE);
2553 } else 2552 } else
2554 vbus_irq = 0; 2553 vbus_irq = 0;
2555 if (dev->mach->gpio_pullup) 2554 if (dev->mach->gpio_pullup)
2556 pxa_gpio_mode((dev->mach->gpio_pullup & GPIO_MD_MASK_NR) 2555 udc_gpio_init_pullup(dev->mach->gpio_pullup);
2557 | GPIO_OUT | GPIO_DFLT_LOW);
2558 2556
2559 init_timer(&dev->timer); 2557 init_timer(&dev->timer);
2560 dev->timer.function = udc_watchdog; 2558 dev->timer.function = udc_watchdog;
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 8e598c8bf4e3..773e549aff3f 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -177,21 +177,6 @@ struct pxa2xx_udc {
177 177
178static struct pxa2xx_udc *the_controller; 178static struct pxa2xx_udc *the_controller;
179 179
180static inline int pxa_gpio_get(unsigned gpio)
181{
182 return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
183}
184
185static inline void pxa_gpio_set(unsigned gpio, int is_on)
186{
187 int mask = GPIO_bit(gpio);
188
189 if (is_on)
190 GPSR(gpio) = mask;
191 else
192 GPCR(gpio) = mask;
193}
194
195/*-------------------------------------------------------------------------*/ 180/*-------------------------------------------------------------------------*/
196 181
197/* 182/*
diff --git a/include/asm-arm/.gitignore b/include/asm-arm/.gitignore
new file mode 100644
index 000000000000..e02c15d158fc
--- /dev/null
+++ b/include/asm-arm/.gitignore
@@ -0,0 +1,2 @@
1arch
2mach-types.h
diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
index 593f562f85c3..625c6f0abc03 100644
--- a/include/asm-arm/arch-ep93xx/ep93xx-regs.h
+++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
@@ -73,6 +73,11 @@
73 73
74#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) 74#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000)
75#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) 75#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x))
76#define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c)
77#define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50)
78#define EP93XX_GPIO_F_INT_ACK EP93XX_GPIO_REG(0x54)
79#define EP93XX_GPIO_F_INT_ENABLE EP93XX_GPIO_REG(0x58)
80#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c)
76#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90) 81#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90)
77#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94) 82#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94)
78#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98) 83#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98)
diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
index ae532e304bf1..2a8c63638c5e 100644
--- a/include/asm-arm/arch-ep93xx/irqs.h
+++ b/include/asm-arm/arch-ep93xx/irqs.h
@@ -67,9 +67,13 @@
67#define IRQ_EP93XX_SAI 60 67#define IRQ_EP93XX_SAI 60
68#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff 68#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff
69 69
70#define IRQ_EP93XX_GPIO(x) (64 + (x)) 70/*
71 * Map GPIO A0..A7 to irq 64..71, B0..B7 to 72..79, and
72 * F0..F7 to 80..87.
73 */
74#define IRQ_EP93XX_GPIO(x) (64 + (((x) + (((x) >> 2) & 8)) & 0x1f))
71 75
72#define NR_EP93XX_IRQS IRQ_EP93XX_GPIO(16) 76#define NR_EP93XX_IRQS (64 + 24)
73 77
74#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) 78#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x))
75#define EP93XX_BOARD_IRQS 32 79#define EP93XX_BOARD_IRQS 32
diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
index b4a8deb8bdef..44eccec2cba4 100644
--- a/include/asm-arm/arch-ep93xx/platform.h
+++ b/include/asm-arm/arch-ep93xx/platform.h
@@ -8,7 +8,6 @@ void ep93xx_map_io(void);
8void ep93xx_init_irq(void); 8void ep93xx_init_irq(void);
9void ep93xx_init_time(unsigned long); 9void ep93xx_init_time(unsigned long);
10void ep93xx_init_devices(void); 10void ep93xx_init_devices(void);
11void ep93xx_clock_init(void);
12extern struct sys_timer ep93xx_timer; 11extern struct sys_timer ep93xx_timer;
13 12
14struct ep93xx_eth_data 13struct ep93xx_eth_data
diff --git a/include/asm-arm/arch-imx/entry-macro.S b/include/asm-arm/arch-imx/entry-macro.S
index 3b9ef6914627..61bb0bdc1b16 100644
--- a/include/asm-arm/arch-imx/entry-macro.S
+++ b/include/asm-arm/arch-imx/entry-macro.S
@@ -13,19 +13,13 @@
13 .endm 13 .endm
14#define AITC_NIVECSR 0x40 14#define AITC_NIVECSR 0x40
15 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp 15 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
16 ldr \irqstat, =IO_ADDRESS(IMX_AITC_BASE) 16 ldr \base, =IO_ADDRESS(IMX_AITC_BASE)
17 @ Load offset & priority of the highest priority 17 @ Load offset & priority of the highest priority
18 @ interrupt pending. 18 @ interrupt pending.
19 ldr \irqnr, [\irqstat, #AITC_NIVECSR] 19 ldr \irqstat, [\base, #AITC_NIVECSR]
20 @ Shift off the priority leaving the offset or 20 @ Shift off the priority leaving the offset or
21 @ "interrupt number" 21 @ "interrupt number", use arithmetic shift to
22 mov \irqnr, \irqnr, lsr #16 22 @ transform illegal source (0xffff) as -1
23 ldr \irqstat, =1 @ dummy compare 23 mov \irqnr, \irqstat, asr #16
24 ldr \base, =0xFFFF // invalid interrupt 24 adds \tmp, \irqnr, #1
25 cmp \irqnr, \base
26 bne 1001f
27 ldr \irqstat, =0
281001:
29 tst \irqstat, #1 @ to make the condition code = TRUE
30 .endm 25 .endm
31
diff --git a/include/asm-arm/arch-ixp4xx/udc.h b/include/asm-arm/arch-ixp4xx/udc.h
index dbdec36ff0d1..79b850a3be47 100644
--- a/include/asm-arm/arch-ixp4xx/udc.h
+++ b/include/asm-arm/arch-ixp4xx/udc.h
@@ -6,3 +6,25 @@
6 6
7extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info); 7extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
8 8
9static inline int udc_gpio_to_irq(unsigned gpio)
10{
11 return 0;
12}
13
14static inline void udc_gpio_init_vbus(unsigned gpio)
15{
16}
17
18static inline void udc_gpio_init_pullup(unsigned gpio)
19{
20}
21
22static inline int udc_gpio_get(unsigned gpio)
23{
24 return 0;
25}
26
27static inline void udc_gpio_set(unsigned gpio, int is_on)
28{
29}
30
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index e24f6b6c79ae..aec835b6f057 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -463,9 +463,6 @@
463 * Serial Audio Controller 463 * Serial Audio Controller
464 */ 464 */
465 465
466/* FIXME: This clash with SA1111 defines */
467#ifndef _ASM_ARCH_SA1111
468
469#define SACR0 __REG(0x40400000) /* Global Control Register */ 466#define SACR0 __REG(0x40400000) /* Global Control Register */
470#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */ 467#define SACR1 __REG(0x40400004) /* Serial Audio I 2 S/MSB-Justified Control Register */
471#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */ 468#define SASR0 __REG(0x4040000C) /* Serial Audio I 2 S/MSB-Justified Interface and FIFO Status Register */
@@ -474,8 +471,8 @@
474#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */ 471#define SADIV __REG(0x40400060) /* Audio Clock Divider Register. */
475#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */ 472#define SADR __REG(0x40400080) /* Serial Audio Data Register (TX and RX FIFO access Register). */
476 473
477#define SACR0_RFTH(x) (x << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */ 474#define SACR0_RFTH(x) ((x) << 12) /* Rx FIFO Interrupt or DMA Trigger Threshold */
478#define SACR0_TFTH(x) (x << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */ 475#define SACR0_TFTH(x) ((x) << 8) /* Tx FIFO Interrupt or DMA Trigger Threshold */
479#define SACR0_STRF (1 << 5) /* FIFO Select for EFWR Special Function */ 476#define SACR0_STRF (1 << 5) /* FIFO Select for EFWR Special Function */
480#define SACR0_EFWR (1 << 4) /* Enable EFWR Function */ 477#define SACR0_EFWR (1 << 4) /* Enable EFWR Function */
481#define SACR0_RST (1 << 3) /* FIFO, i2s Register Reset */ 478#define SACR0_RST (1 << 3) /* FIFO, i2s Register Reset */
@@ -503,8 +500,6 @@
503#define SAIMR_RFS (1 << 4) /* Enable Rx FIFO Service Interrupt */ 500#define SAIMR_RFS (1 << 4) /* Enable Rx FIFO Service Interrupt */
504#define SAIMR_TFS (1 << 3) /* Enable Tx FIFO Service Interrupt */ 501#define SAIMR_TFS (1 << 3) /* Enable Tx FIFO Service Interrupt */
505 502
506#endif
507
508/* 503/*
509 * AC97 Controller registers 504 * AC97 Controller registers
510 */ 505 */
@@ -1682,15 +1677,18 @@
1682#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ 1677#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */
1683 1678
1684#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ 1679#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */
1685#define SSPSP_DMYSTOP(x) (x << 23) /* Dummy Stop */ 1680#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */
1686#define SSPSP_SFRMWDTH(x) (x << 16) /* Serial Frame Width */ 1681#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */
1687#define SSPSP_SFRMDLY(x) (x << 9) /* Serial Frame Delay */ 1682#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */
1688#define SSPSP_DMYSTRT(x) (x << 7) /* Dummy Start */ 1683#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */
1689#define SSPSP_STRTDLY(x) (x << 4) /* Start Delay */ 1684#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */
1690#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */ 1685#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */
1691#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */ 1686#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */
1692#define SSPSP_SCMODE(x) (x << 0) /* Serial Bit Rate Clock Mode */ 1687#define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */
1693 1688
1689#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */
1690#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */
1691#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */
1694 1692
1695#define SSCR0_P1 __REG(0x41000000) /* SSP Port 1 Control Register 0 */ 1693#define SSCR0_P1 __REG(0x41000000) /* SSP Port 1 Control Register 0 */
1696#define SSCR1_P1 __REG(0x41000004) /* SSP Port 1 Control Register 1 */ 1694#define SSCR1_P1 __REG(0x41000004) /* SSP Port 1 Control Register 1 */
diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h
index 646480d37256..8bc6f9c3e3ea 100644
--- a/include/asm-arm/arch-pxa/udc.h
+++ b/include/asm-arm/arch-pxa/udc.h
@@ -9,3 +9,33 @@
9 9
10extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info); 10extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
11 11
12static inline int udc_gpio_to_irq(unsigned gpio)
13{
14 return IRQ_GPIO(gpio & GPIO_MD_MASK_NR);
15}
16
17static inline void udc_gpio_init_vbus(unsigned gpio)
18{
19 pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_IN);
20}
21
22static inline void udc_gpio_init_pullup(unsigned gpio)
23{
24 pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_OUT | GPIO_DFLT_LOW);
25}
26
27static inline int udc_gpio_get(unsigned gpio)
28{
29 return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
30}
31
32static inline void udc_gpio_set(unsigned gpio, int is_on)
33{
34 int mask = GPIO_bit(gpio);
35
36 if (is_on)
37 GPSR(gpio) = mask;
38 else
39 GPCR(gpio) = mask;
40}
41
diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
index 9ca76dc3a7af..aa78fe087ab2 100644
--- a/include/asm-arm/arch-realview/hardware.h
+++ b/include/asm-arm/arch-realview/hardware.h
@@ -26,7 +26,7 @@
26#include <asm/arch/platform.h> 26#include <asm/arch/platform.h>
27 27
28/* macro to get at IO space when running virtually */ 28/* macro to get at IO space when running virtually */
29#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) 29#define IO_ADDRESS(x) ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
30#define __io_address(n) __io(IO_ADDRESS(n)) 30#define __io_address(n) __io(IO_ADDRESS(n))
31 31
32#endif 32#endif
diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h
index 76b498eb20a6..5a5db56f86b8 100644
--- a/include/asm-arm/arch-realview/irqs.h
+++ b/include/asm-arm/arch-realview/irqs.h
@@ -78,6 +78,9 @@
78#define IRQ_PMU_SCU6 (IRQ_GIC_START + INT_PMU_SCU6) 78#define IRQ_PMU_SCU6 (IRQ_GIC_START + INT_PMU_SCU6)
79#define IRQ_PMU_SCU7 (IRQ_GIC_START + INT_PMU_SCU7) 79#define IRQ_PMU_SCU7 (IRQ_GIC_START + INT_PMU_SCU7)
80 80
81#define IRQ_EB_IRQ1 (IRQ_GIC_START + INT_EB_IRQ1)
82#define IRQ_EB_IRQ2 (IRQ_GIC_START + INT_EB_IRQ2)
83
81#define IRQMASK_WDOGINT INTMASK_WDOGINT 84#define IRQMASK_WDOGINT INTMASK_WDOGINT
82#define IRQMASK_SOFTINT INTMASK_SOFTINT 85#define IRQMASK_SOFTINT INTMASK_SOFTINT
83#define IRQMASK_COMMRx INTMASK_COMMRx 86#define IRQMASK_COMMRx INTMASK_COMMRx
@@ -115,4 +118,4 @@
115#define IRQMASK_ETH INTMASK_ETH 118#define IRQMASK_ETH INTMASK_ETH
116#define IRQMASK_USB INTMASK_USB 119#define IRQMASK_USB INTMASK_USB
117 120
118#define NR_IRQS (IRQ_GIC_START + 64) 121#define NR_IRQS (IRQ_GIC_START + 96)
diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
index 18d7c18b738c..6e0eab95a3a2 100644
--- a/include/asm-arm/arch-realview/platform.h
+++ b/include/asm-arm/arch-realview/platform.h
@@ -207,11 +207,25 @@
207#define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ 207#define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
208#define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ 208#define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
209#else 209#else
210#ifdef CONFIG_REALVIEW_MPCORE_REVB
210#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ 211#define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */
211#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ 212#define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
212#define REALVIEW_TWD_BASE 0x10100700 213#define REALVIEW_TWD_BASE 0x10100700
213#define REALVIEW_TWD_SIZE 0x00000100 214#define REALVIEW_TWD_SIZE 0x00000100
214#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ 215#define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
216#define REALVIEW_MPCORE_L220_BASE 0x10102000 /* L220 registers */
217#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
218#else
219#define REALVIEW_MPCORE_SCU_BASE 0x1F000000 /* SCU registers */
220#define REALVIEW_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
221#define REALVIEW_TWD_BASE 0x1F000700
222#define REALVIEW_TWD_SIZE 0x00000100
223#define REALVIEW_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
224#define REALVIEW_MPCORE_L220_BASE 0x1F002000 /* L220 registers */
225#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
226#endif
227#define REALVIEW_GIC1_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */
228#define REALVIEW_GIC1_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */
215#endif 229#endif
216#define REALVIEW_SMC_BASE 0x10080000 /* SMC */ 230#define REALVIEW_SMC_BASE 0x10080000 /* SMC */
217 /* Reserved 0x10090000 - 0x100EFFFF */ 231 /* Reserved 0x10090000 - 0x100EFFFF */
@@ -306,7 +320,11 @@
306#define INT_USB 29 /* USB controller */ 320#define INT_USB 29 /* USB controller */
307#define INT_TSPENINT 30 /* Touchscreen pen */ 321#define INT_TSPENINT 30 /* Touchscreen pen */
308#define INT_TSKPADINT 31 /* Touchscreen keypad */ 322#define INT_TSKPADINT 31 /* Touchscreen keypad */
323
309#else 324#else
325
326#define MAX_GIC_NR 2
327
310#define INT_AACI 0 328#define INT_AACI 0
311#define INT_TIMERINT0_1 1 329#define INT_TIMERINT0_1 1
312#define INT_TIMERINT2_3 2 330#define INT_TIMERINT2_3 2
diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h
new file mode 100644
index 000000000000..cc293640178e
--- /dev/null
+++ b/include/asm-arm/arch-realview/scu.h
@@ -0,0 +1,8 @@
1#ifndef __ASMARM_ARCH_SCU_H
2#define __ASMARM_ARCH_SCU_H
3
4#include <asm/arch/platform.h>
5
6#define SCU_BASE REALVIEW_MPCORE_SCU_BASE
7
8#endif
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index 58ffa7ba3c88..c6e8d8f64938 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -51,13 +51,19 @@ enum dma_ch {
51 DMACH_UART0_SRC2, /* s3c2412 second uart sources */ 51 DMACH_UART0_SRC2, /* s3c2412 second uart sources */
52 DMACH_UART1_SRC2, 52 DMACH_UART1_SRC2,
53 DMACH_UART2_SRC2, 53 DMACH_UART2_SRC2,
54 DMACH_UART3, /* s3c2443 has extra uart */
55 DMACH_UART3_SRC2,
54 DMACH_MAX, /* the end entry */ 56 DMACH_MAX, /* the end entry */
55}; 57};
56 58
57#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */ 59#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
58 60
59/* we have 4 dma channels */ 61/* we have 4 dma channels */
60#define S3C2410_DMA_CHANNELS (4) 62#ifndef CONFIG_CPU_S3C2443
63#define S3C2410_DMA_CHANNELS (4)
64#else
65#define S3C2410_DMA_CHANNELS (6)
66#endif
61 67
62/* types */ 68/* types */
63 69
@@ -321,6 +327,7 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
321#define S3C2410_DMA_DCDST (0x1C) 327#define S3C2410_DMA_DCDST (0x1C)
322#define S3C2410_DMA_DMASKTRIG (0x20) 328#define S3C2410_DMA_DMASKTRIG (0x20)
323#define S3C2412_DMA_DMAREQSEL (0x24) 329#define S3C2412_DMA_DMAREQSEL (0x24)
330#define S3C2443_DMA_DMAREQSEL (0x24)
324 331
325#define S3C2410_DISRCC_INC (1<<0) 332#define S3C2410_DISRCC_INC (1<<0)
326#define S3C2410_DISRCC_APB (1<<1) 333#define S3C2410_DISRCC_APB (1<<1)
@@ -415,4 +422,31 @@ extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
415#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24) 422#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
416 423
417#endif 424#endif
425
426#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
427
428#define S3C2443_DMAREQSEL_HW (1)
429
430#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
431#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
432#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
433#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
434#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
435#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
436#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
437#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
438#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
439#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
440#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
441#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
442#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
443#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
444#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
445#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
446#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
447#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
448#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
449#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
450#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
451
418#endif /* __ASM_ARCH_DMA_H */ 452#endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index 4b7cff456c4e..c79cb1819913 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -34,10 +34,10 @@
34#define IRQ_EINT4t7 S3C2410_IRQ(4) /* 20 */ 34#define IRQ_EINT4t7 S3C2410_IRQ(4) /* 20 */
35#define IRQ_EINT8t23 S3C2410_IRQ(5) 35#define IRQ_EINT8t23 S3C2410_IRQ(5)
36#define IRQ_RESERVED6 S3C2410_IRQ(6) /* for s3c2410 */ 36#define IRQ_RESERVED6 S3C2410_IRQ(6) /* for s3c2410 */
37#define IRQ_CAM S3C2410_IRQ(6) /* for s3c2440 */ 37#define IRQ_CAM S3C2410_IRQ(6) /* for s3c2440,s3c2443 */
38#define IRQ_BATT_FLT S3C2410_IRQ(7) 38#define IRQ_BATT_FLT S3C2410_IRQ(7)
39#define IRQ_TICK S3C2410_IRQ(8) /* 24 */ 39#define IRQ_TICK S3C2410_IRQ(8) /* 24 */
40#define IRQ_WDT S3C2410_IRQ(9) 40#define IRQ_WDT S3C2410_IRQ(9) /* WDT/AC97 for s3c2443 */
41#define IRQ_TIMER0 S3C2410_IRQ(10) 41#define IRQ_TIMER0 S3C2410_IRQ(10)
42#define IRQ_TIMER1 S3C2410_IRQ(11) 42#define IRQ_TIMER1 S3C2410_IRQ(11)
43#define IRQ_TIMER2 S3C2410_IRQ(12) 43#define IRQ_TIMER2 S3C2410_IRQ(12)
@@ -45,7 +45,7 @@
45#define IRQ_TIMER4 S3C2410_IRQ(14) 45#define IRQ_TIMER4 S3C2410_IRQ(14)
46#define IRQ_UART2 S3C2410_IRQ(15) 46#define IRQ_UART2 S3C2410_IRQ(15)
47#define IRQ_LCD S3C2410_IRQ(16) /* 32 */ 47#define IRQ_LCD S3C2410_IRQ(16) /* 32 */
48#define IRQ_DMA0 S3C2410_IRQ(17) 48#define IRQ_DMA0 S3C2410_IRQ(17) /* IRQ_DMA for s3c2443 */
49#define IRQ_DMA1 S3C2410_IRQ(18) 49#define IRQ_DMA1 S3C2410_IRQ(18)
50#define IRQ_DMA2 S3C2410_IRQ(19) 50#define IRQ_DMA2 S3C2410_IRQ(19)
51#define IRQ_DMA3 S3C2410_IRQ(20) 51#define IRQ_DMA3 S3C2410_IRQ(20)
@@ -94,29 +94,63 @@
94 * these need to be ordered in number of appearance in the 94 * these need to be ordered in number of appearance in the
95 * SUBSRC mask register 95 * SUBSRC mask register
96*/ 96*/
97#define IRQ_S3CUART_RX0 S3C2410_IRQ(54) /* 70 */
98#define IRQ_S3CUART_TX0 S3C2410_IRQ(55) /* 71 */
99#define IRQ_S3CUART_ERR0 S3C2410_IRQ(56)
100 97
101#define IRQ_S3CUART_RX1 S3C2410_IRQ(57) 98#define S3C2410_IRQSUB(x) S3C2410_IRQ((x)+54)
102#define IRQ_S3CUART_TX1 S3C2410_IRQ(58)
103#define IRQ_S3CUART_ERR1 S3C2410_IRQ(59)
104 99
105#define IRQ_S3CUART_RX2 S3C2410_IRQ(60) 100#define IRQ_S3CUART_RX0 S3C2410_IRQSUB(0) /* 70 */
106#define IRQ_S3CUART_TX2 S3C2410_IRQ(61) 101#define IRQ_S3CUART_TX0 S3C2410_IRQSUB(1)
107#define IRQ_S3CUART_ERR2 S3C2410_IRQ(62) 102#define IRQ_S3CUART_ERR0 S3C2410_IRQSUB(2)
108 103
109#define IRQ_TC S3C2410_IRQ(63) 104#define IRQ_S3CUART_RX1 S3C2410_IRQSUB(3) /* 73 */
110#define IRQ_ADC S3C2410_IRQ(64) 105#define IRQ_S3CUART_TX1 S3C2410_IRQSUB(4)
106#define IRQ_S3CUART_ERR1 S3C2410_IRQSUB(5)
111 107
112/* extra irqs for s3c2440 */ 108#define IRQ_S3CUART_RX2 S3C2410_IRQSUB(6) /* 76 */
109#define IRQ_S3CUART_TX2 S3C2410_IRQSUB(7)
110#define IRQ_S3CUART_ERR2 S3C2410_IRQSUB(8)
113 111
114#define IRQ_S3C2440_CAM_C S3C2410_IRQ(65) 112#define IRQ_TC S3C2410_IRQSUB(9)
115#define IRQ_S3C2440_CAM_P S3C2410_IRQ(66) 113#define IRQ_ADC S3C2410_IRQSUB(10)
116#define IRQ_S3C2440_WDT S3C2410_IRQ(67)
117#define IRQ_S3C2440_AC97 S3C2410_IRQ(68)
118 114
119#define NR_IRQS (IRQ_S3C2440_AC97+1) 115/* extra irqs for s3c2440 */
120 116
117#define IRQ_S3C2440_CAM_C S3C2410_IRQSUB(11) /* S3C2443 too */
118#define IRQ_S3C2440_CAM_P S3C2410_IRQSUB(12) /* S3C2443 too */
119#define IRQ_S3C2440_WDT S3C2410_IRQSUB(13)
120#define IRQ_S3C2440_AC97 S3C2410_IRQSUB(14)
121
122/* irqs for s3c2443 */
123
124#define IRQ_S3C2443_DMA S3C2410_IRQ(17) /* IRQ_DMA1 */
125#define IRQ_S3C2443_UART3 S3C2410_IRQ(18) /* IRQ_DMA2 */
126#define IRQ_S3C2443_CFCON S3C2410_IRQ(19) /* IRQ_DMA3 */
127#define IRQ_S3C2443_SDI1 S3C2410_IRQ(20) /* IRQ_SDI */
128#define IRQ_S3C2443_NAND S3C2410_IRQ(24) /* reserved */
129
130#define IRQ_S3C2443_LCD1 S3C2410_IRQSUB(14)
131#define IRQ_S3C2443_LCD2 S3C2410_IRQSUB(15)
132#define IRQ_S3C2443_LCD3 S3C2410_IRQSUB(16)
133#define IRQ_S3C2443_LCD4 S3C2410_IRQSUB(17)
134
135#define IRQ_S3C2443_DMA0 S3C2410_IRQSUB(18)
136#define IRQ_S3C2443_DMA1 S3C2410_IRQSUB(19)
137#define IRQ_S3C2443_DMA2 S3C2410_IRQSUB(20)
138#define IRQ_S3C2443_DMA3 S3C2410_IRQSUB(21)
139#define IRQ_S3C2443_DMA4 S3C2410_IRQSUB(22)
140#define IRQ_S3C2443_DMA5 S3C2410_IRQSUB(23)
141
142/* UART3 */
143#define IRQ_S3C2443_RX3 S3C2410_IRQSUB(24)
144#define IRQ_S3C2443_TX3 S3C2410_IRQSUB(25)
145#define IRQ_S3C2443_ERR3 S3C2410_IRQSUB(26)
146
147#define IRQ_S3C2443_WDT S3C2410_IRQSUB(27)
148#define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28)
149
150#ifdef CONFIG_CPU_S3C2443
151#define NR_IRQS (IRQ_S3C2443_AC97+1)
152#else
153#define NR_IRQS (IRQ_S3C2440_AC97+1)
154#endif
121 155
122#endif /* __ASM_ARCH_IRQ_H */ 156#endif /* __ASM_ARCH_IRQ_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.h
index 3196a2849e8a..c7f231963e76 100644
--- a/include/asm-arm/arch-s3c2410/regs-adc.h
+++ b/include/asm-arm/arch-s3c2410/regs-adc.h
@@ -41,7 +41,7 @@
41#define S3C2410_ADCTSC_XP_SEN (1<<4) 41#define S3C2410_ADCTSC_XP_SEN (1<<4)
42#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3) 42#define S3C2410_ADCTSC_PULL_UP_DISABLE (1<<3)
43#define S3C2410_ADCTSC_AUTO_PST (1<<2) 43#define S3C2410_ADCTSC_AUTO_PST (1<<2)
44#define S3C2410_ADCTSC_XY_PST (0x3<<0) 44#define S3C2410_ADCTSC_XY_PST(x) (((x)&0x3)<<0)
45 45
46/* ADCDAT0 Bits */ 46/* ADCDAT0 Bits */
47#define S3C2410_ADCDAT0_UPDOWN (1<<15) 47#define S3C2410_ADCDAT0_UPDOWN (1<<15)
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index eae91694edcd..dea578b8f7f6 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -201,7 +201,7 @@
201#define S3C2400_GPBDAT S3C2410_GPIOREG(0x0C) 201#define S3C2400_GPBDAT S3C2410_GPIOREG(0x0C)
202#define S3C2400_GPBUP S3C2410_GPIOREG(0x10) 202#define S3C2400_GPBUP S3C2410_GPIOREG(0x10)
203 203
204/* no i/o pin in port b can have value 3! */ 204/* no i/o pin in port b can have value 3 (unless it is a s3c2443) ! */
205 205
206#define S3C2410_GPB0 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0) 206#define S3C2410_GPB0 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 0)
207#define S3C2410_GPB0_INP (0x00 << 0) 207#define S3C2410_GPB0_INP (0x00 << 0)
@@ -242,6 +242,7 @@
242#define S3C2410_GPB5_INP (0x00 << 10) 242#define S3C2410_GPB5_INP (0x00 << 10)
243#define S3C2410_GPB5_OUTP (0x01 << 10) 243#define S3C2410_GPB5_OUTP (0x01 << 10)
244#define S3C2410_GPB5_nXBACK (0x02 << 10) 244#define S3C2410_GPB5_nXBACK (0x02 << 10)
245#define S3C2443_GPB5_XBACK (0x03 << 10)
245#define S3C2400_GPB5_DATA21 (0x02 << 10) 246#define S3C2400_GPB5_DATA21 (0x02 << 10)
246#define S3C2400_GPB5_nCTS1 (0x03 << 10) 247#define S3C2400_GPB5_nCTS1 (0x03 << 10)
247 248
@@ -249,6 +250,7 @@
249#define S3C2410_GPB6_INP (0x00 << 12) 250#define S3C2410_GPB6_INP (0x00 << 12)
250#define S3C2410_GPB6_OUTP (0x01 << 12) 251#define S3C2410_GPB6_OUTP (0x01 << 12)
251#define S3C2410_GPB6_nXBREQ (0x02 << 12) 252#define S3C2410_GPB6_nXBREQ (0x02 << 12)
253#define S3C2443_GPB6_XBREQ (0x03 << 12)
252#define S3C2400_GPB6_DATA22 (0x02 << 12) 254#define S3C2400_GPB6_DATA22 (0x02 << 12)
253#define S3C2400_GPB6_nRTS1 (0x03 << 12) 255#define S3C2400_GPB6_nRTS1 (0x03 << 12)
254 256
@@ -256,6 +258,7 @@
256#define S3C2410_GPB7_INP (0x00 << 14) 258#define S3C2410_GPB7_INP (0x00 << 14)
257#define S3C2410_GPB7_OUTP (0x01 << 14) 259#define S3C2410_GPB7_OUTP (0x01 << 14)
258#define S3C2410_GPB7_nXDACK1 (0x02 << 14) 260#define S3C2410_GPB7_nXDACK1 (0x02 << 14)
261#define S3C2443_GPB7_XDACK1 (0x03 << 14)
259#define S3C2400_GPB7_DATA23 (0x02 << 14) 262#define S3C2400_GPB7_DATA23 (0x02 << 14)
260 263
261#define S3C2410_GPB8 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 8) 264#define S3C2410_GPB8 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 8)
@@ -268,6 +271,7 @@
268#define S3C2410_GPB9_INP (0x00 << 18) 271#define S3C2410_GPB9_INP (0x00 << 18)
269#define S3C2410_GPB9_OUTP (0x01 << 18) 272#define S3C2410_GPB9_OUTP (0x01 << 18)
270#define S3C2410_GPB9_nXDACK0 (0x02 << 18) 273#define S3C2410_GPB9_nXDACK0 (0x02 << 18)
274#define S3C2443_GPB9_XDACK0 (0x03 << 18)
271#define S3C2400_GPB9_DATA25 (0x02 << 18) 275#define S3C2400_GPB9_DATA25 (0x02 << 18)
272#define S3C2400_GPB9_I2SSDI (0x03 << 18) 276#define S3C2400_GPB9_I2SSDI (0x03 << 18)
273 277
@@ -275,6 +279,7 @@
275#define S3C2410_GPB10_INP (0x00 << 20) 279#define S3C2410_GPB10_INP (0x00 << 20)
276#define S3C2410_GPB10_OUTP (0x01 << 20) 280#define S3C2410_GPB10_OUTP (0x01 << 20)
277#define S3C2410_GPB10_nXDRE0 (0x02 << 20) 281#define S3C2410_GPB10_nXDRE0 (0x02 << 20)
282#define S3C2443_GPB10_XDREQ0 (0x03 << 20)
278#define S3C2400_GPB10_DATA26 (0x02 << 20) 283#define S3C2400_GPB10_DATA26 (0x02 << 20)
279#define S3C2400_GPB10_nSS (0x03 << 20) 284#define S3C2400_GPB10_nSS (0x03 << 20)
280 285
@@ -556,6 +561,7 @@
556#define S3C2410_GPE0_INP (0x00 << 0) 561#define S3C2410_GPE0_INP (0x00 << 0)
557#define S3C2410_GPE0_OUTP (0x01 << 0) 562#define S3C2410_GPE0_OUTP (0x01 << 0)
558#define S3C2410_GPE0_I2SLRCK (0x02 << 0) 563#define S3C2410_GPE0_I2SLRCK (0x02 << 0)
564#define S3C2443_GPE0_AC_nRESET (0x03 << 0)
559#define S3C2400_GPE0_EINT0 (0x02 << 0) 565#define S3C2400_GPE0_EINT0 (0x02 << 0)
560#define S3C2410_GPE0_MASK (0x03 << 0) 566#define S3C2410_GPE0_MASK (0x03 << 0)
561 567
@@ -563,6 +569,7 @@
563#define S3C2410_GPE1_INP (0x00 << 2) 569#define S3C2410_GPE1_INP (0x00 << 2)
564#define S3C2410_GPE1_OUTP (0x01 << 2) 570#define S3C2410_GPE1_OUTP (0x01 << 2)
565#define S3C2410_GPE1_I2SSCLK (0x02 << 2) 571#define S3C2410_GPE1_I2SSCLK (0x02 << 2)
572#define S3C2443_GPE1_AC_SYNC (0x03 << 2)
566#define S3C2400_GPE1_EINT1 (0x02 << 2) 573#define S3C2400_GPE1_EINT1 (0x02 << 2)
567#define S3C2400_GPE1_nSS (0x03 << 2) 574#define S3C2400_GPE1_nSS (0x03 << 2)
568#define S3C2410_GPE1_MASK (0x03 << 2) 575#define S3C2410_GPE1_MASK (0x03 << 2)
@@ -571,6 +578,7 @@
571#define S3C2410_GPE2_INP (0x00 << 4) 578#define S3C2410_GPE2_INP (0x00 << 4)
572#define S3C2410_GPE2_OUTP (0x01 << 4) 579#define S3C2410_GPE2_OUTP (0x01 << 4)
573#define S3C2410_GPE2_CDCLK (0x02 << 4) 580#define S3C2410_GPE2_CDCLK (0x02 << 4)
581#define S3C2443_GPE2_AC_BITCLK (0x03 << 4)
574#define S3C2400_GPE2_EINT2 (0x02 << 4) 582#define S3C2400_GPE2_EINT2 (0x02 << 4)
575#define S3C2400_GPE2_I2SSDI (0x03 << 4) 583#define S3C2400_GPE2_I2SSDI (0x03 << 4)
576 584
@@ -578,6 +586,7 @@
578#define S3C2410_GPE3_INP (0x00 << 6) 586#define S3C2410_GPE3_INP (0x00 << 6)
579#define S3C2410_GPE3_OUTP (0x01 << 6) 587#define S3C2410_GPE3_OUTP (0x01 << 6)
580#define S3C2410_GPE3_I2SSDI (0x02 << 6) 588#define S3C2410_GPE3_I2SSDI (0x02 << 6)
589#define S3C2443_GPE3_AC_SDI (0x03 << 6)
581#define S3C2400_GPE3_EINT3 (0x02 << 6) 590#define S3C2400_GPE3_EINT3 (0x02 << 6)
582#define S3C2400_GPE3_nCTS1 (0x03 << 6) 591#define S3C2400_GPE3_nCTS1 (0x03 << 6)
583#define S3C2410_GPE3_nSS0 (0x03 << 6) 592#define S3C2410_GPE3_nSS0 (0x03 << 6)
@@ -587,6 +596,7 @@
587#define S3C2410_GPE4_INP (0x00 << 8) 596#define S3C2410_GPE4_INP (0x00 << 8)
588#define S3C2410_GPE4_OUTP (0x01 << 8) 597#define S3C2410_GPE4_OUTP (0x01 << 8)
589#define S3C2410_GPE4_I2SSDO (0x02 << 8) 598#define S3C2410_GPE4_I2SSDO (0x02 << 8)
599#define S3C2443_GPE4_AC_SDO (0x03 << 8)
590#define S3C2400_GPE4_EINT4 (0x02 << 8) 600#define S3C2400_GPE4_EINT4 (0x02 << 8)
591#define S3C2400_GPE4_nRTS1 (0x03 << 8) 601#define S3C2400_GPE4_nRTS1 (0x03 << 8)
592#define S3C2410_GPE4_I2SSDI (0x03 << 8) 602#define S3C2410_GPE4_I2SSDI (0x03 << 8)
@@ -596,6 +606,7 @@
596#define S3C2410_GPE5_INP (0x00 << 10) 606#define S3C2410_GPE5_INP (0x00 << 10)
597#define S3C2410_GPE5_OUTP (0x01 << 10) 607#define S3C2410_GPE5_OUTP (0x01 << 10)
598#define S3C2410_GPE5_SDCLK (0x02 << 10) 608#define S3C2410_GPE5_SDCLK (0x02 << 10)
609#define S3C2443_GPE5_SD1_CLK (0x02 << 10)
599#define S3C2400_GPE5_EINT5 (0x02 << 10) 610#define S3C2400_GPE5_EINT5 (0x02 << 10)
600#define S3C2400_GPE5_TCLK1 (0x03 << 10) 611#define S3C2400_GPE5_TCLK1 (0x03 << 10)
601 612
@@ -603,24 +614,32 @@
603#define S3C2410_GPE6_INP (0x00 << 12) 614#define S3C2410_GPE6_INP (0x00 << 12)
604#define S3C2410_GPE6_OUTP (0x01 << 12) 615#define S3C2410_GPE6_OUTP (0x01 << 12)
605#define S3C2410_GPE6_SDCMD (0x02 << 12) 616#define S3C2410_GPE6_SDCMD (0x02 << 12)
617#define S3C2443_GPE6_SD1_CMD (0x02 << 12)
618#define S3C2443_GPE6_AC_BITCLK (0x03 << 12)
606#define S3C2400_GPE6_EINT6 (0x02 << 12) 619#define S3C2400_GPE6_EINT6 (0x02 << 12)
607 620
608#define S3C2410_GPE7 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 7) 621#define S3C2410_GPE7 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 7)
609#define S3C2410_GPE7_INP (0x00 << 14) 622#define S3C2410_GPE7_INP (0x00 << 14)
610#define S3C2410_GPE7_OUTP (0x01 << 14) 623#define S3C2410_GPE7_OUTP (0x01 << 14)
611#define S3C2410_GPE7_SDDAT0 (0x02 << 14) 624#define S3C2410_GPE7_SDDAT0 (0x02 << 14)
625#define S3C2443_GPE5_SD1_DAT0 (0x02 << 14)
626#define S3C2443_GPE7_AC_SDI (0x03 << 14)
612#define S3C2400_GPE7_EINT7 (0x02 << 14) 627#define S3C2400_GPE7_EINT7 (0x02 << 14)
613 628
614#define S3C2410_GPE8 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 8) 629#define S3C2410_GPE8 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 8)
615#define S3C2410_GPE8_INP (0x00 << 16) 630#define S3C2410_GPE8_INP (0x00 << 16)
616#define S3C2410_GPE8_OUTP (0x01 << 16) 631#define S3C2410_GPE8_OUTP (0x01 << 16)
617#define S3C2410_GPE8_SDDAT1 (0x02 << 16) 632#define S3C2410_GPE8_SDDAT1 (0x02 << 16)
633#define S3C2443_GPE8_SD1_DAT1 (0x02 << 16)
634#define S3C2443_GPE8_AC_SDO (0x03 << 16)
618#define S3C2400_GPE8_nXDACK0 (0x02 << 16) 635#define S3C2400_GPE8_nXDACK0 (0x02 << 16)
619 636
620#define S3C2410_GPE9 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 9) 637#define S3C2410_GPE9 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 9)
621#define S3C2410_GPE9_INP (0x00 << 18) 638#define S3C2410_GPE9_INP (0x00 << 18)
622#define S3C2410_GPE9_OUTP (0x01 << 18) 639#define S3C2410_GPE9_OUTP (0x01 << 18)
623#define S3C2410_GPE9_SDDAT2 (0x02 << 18) 640#define S3C2410_GPE9_SDDAT2 (0x02 << 18)
641#define S3C2443_GPE9_SD1_DAT2 (0x02 << 18)
642#define S3C2443_GPE9_AC_SYNC (0x03 << 18)
624#define S3C2400_GPE9_nXDACK1 (0x02 << 18) 643#define S3C2400_GPE9_nXDACK1 (0x02 << 18)
625#define S3C2400_GPE9_nXBACK (0x03 << 18) 644#define S3C2400_GPE9_nXBACK (0x03 << 18)
626 645
@@ -628,6 +647,8 @@
628#define S3C2410_GPE10_INP (0x00 << 20) 647#define S3C2410_GPE10_INP (0x00 << 20)
629#define S3C2410_GPE10_OUTP (0x01 << 20) 648#define S3C2410_GPE10_OUTP (0x01 << 20)
630#define S3C2410_GPE10_SDDAT3 (0x02 << 20) 649#define S3C2410_GPE10_SDDAT3 (0x02 << 20)
650#define S3C2443_GPE10_SD1_DAT3 (0x02 << 20)
651#define S3C2443_GPE10_AC_nRESET (0x03 << 20)
631#define S3C2400_GPE10_nXDREQ0 (0x02 << 20) 652#define S3C2400_GPE10_nXDREQ0 (0x02 << 20)
632 653
633#define S3C2410_GPE11 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 11) 654#define S3C2410_GPE11 S3C2410_GPIONO(S3C2410_GPIO_BANKE, 11)
@@ -796,6 +817,7 @@
796#define S3C2400_GPG4_MMCCLK (0x02 << 8) 817#define S3C2400_GPG4_MMCCLK (0x02 << 8)
797#define S3C2400_GPG4_I2SSDI (0x03 << 8) 818#define S3C2400_GPG4_I2SSDI (0x03 << 8)
798#define S3C2410_GPG4_LCDPWREN (0x03 << 8) 819#define S3C2410_GPG4_LCDPWREN (0x03 << 8)
820#define S3C2443_GPG4_LCDPWRDN (0x03 << 8)
799 821
800#define S3C2410_GPG5 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 5) 822#define S3C2410_GPG5 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 5)
801#define S3C2410_GPG5_INP (0x00 << 10) 823#define S3C2410_GPG5_INP (0x00 << 10)
@@ -803,7 +825,7 @@
803#define S3C2410_GPG5_EINT13 (0x02 << 10) 825#define S3C2410_GPG5_EINT13 (0x02 << 10)
804#define S3C2400_GPG5_MMCCMD (0x02 << 10) 826#define S3C2400_GPG5_MMCCMD (0x02 << 10)
805#define S3C2400_GPG5_IICSDA (0x03 << 10) 827#define S3C2400_GPG5_IICSDA (0x03 << 10)
806#define S3C2410_GPG5_SPIMISO1 (0x03 << 10) 828#define S3C2410_GPG5_SPIMISO1 (0x03 << 10) /* not s3c2443 */
807 829
808#define S3C2410_GPG6 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 6) 830#define S3C2410_GPG6 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 6)
809#define S3C2410_GPG6_INP (0x00 << 12) 831#define S3C2410_GPG6_INP (0x00 << 12)
@@ -845,6 +867,7 @@
845#define S3C2410_GPG11_OUTP (0x01 << 22) 867#define S3C2410_GPG11_OUTP (0x01 << 22)
846#define S3C2410_GPG11_EINT19 (0x02 << 22) 868#define S3C2410_GPG11_EINT19 (0x02 << 22)
847#define S3C2410_GPG11_TCLK1 (0x03 << 22) 869#define S3C2410_GPG11_TCLK1 (0x03 << 22)
870#define S3C2443_GPG11_CF_nIREQ (0x03 << 22)
848 871
849#define S3C2410_GPG12 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12) 872#define S3C2410_GPG12 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
850#define S3C2410_GPG12_INP (0x00 << 24) 873#define S3C2410_GPG12_INP (0x00 << 24)
@@ -852,25 +875,28 @@
852#define S3C2410_GPG12_EINT20 (0x02 << 24) 875#define S3C2410_GPG12_EINT20 (0x02 << 24)
853#define S3C2410_GPG12_XMON (0x03 << 24) 876#define S3C2410_GPG12_XMON (0x03 << 24)
854#define S3C2442_GPG12_nSPICS0 (0x03 << 24) 877#define S3C2442_GPG12_nSPICS0 (0x03 << 24)
878#define S3C2443_GPG12_nINPACK (0x03 << 24)
855 879
856#define S3C2410_GPG13 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13) 880#define S3C2410_GPG13 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
857#define S3C2410_GPG13_INP (0x00 << 26) 881#define S3C2410_GPG13_INP (0x00 << 26)
858#define S3C2410_GPG13_OUTP (0x01 << 26) 882#define S3C2410_GPG13_OUTP (0x01 << 26)
859#define S3C2410_GPG13_EINT21 (0x02 << 26) 883#define S3C2410_GPG13_EINT21 (0x02 << 26)
860#define S3C2410_GPG13_nXPON (0x03 << 26) 884#define S3C2410_GPG13_nXPON (0x03 << 26)
885#define S3C2443_GPG13_CF_nREG (0x03 << 26)
861 886
862#define S3C2410_GPG14 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14) 887#define S3C2410_GPG14 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
863#define S3C2410_GPG14_INP (0x00 << 28) 888#define S3C2410_GPG14_INP (0x00 << 28)
864#define S3C2410_GPG14_OUTP (0x01 << 28) 889#define S3C2410_GPG14_OUTP (0x01 << 28)
865#define S3C2410_GPG14_EINT22 (0x02 << 28) 890#define S3C2410_GPG14_EINT22 (0x02 << 28)
866#define S3C2410_GPG14_YMON (0x03 << 28) 891#define S3C2410_GPG14_YMON (0x03 << 28)
892#define S3C2443_GPG14_CF_RESET (0x03 << 28)
867 893
868#define S3C2410_GPG15 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15) 894#define S3C2410_GPG15 S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
869#define S3C2410_GPG15_INP (0x00 << 30) 895#define S3C2410_GPG15_INP (0x00 << 30)
870#define S3C2410_GPG15_OUTP (0x01 << 30) 896#define S3C2410_GPG15_OUTP (0x01 << 30)
871#define S3C2410_GPG15_EINT23 (0x02 << 30) 897#define S3C2410_GPG15_EINT23 (0x02 << 30)
872#define S3C2410_GPG15_nYPON (0x03 << 30) 898#define S3C2410_GPG15_nYPON (0x03 << 30)
873 899#define S3C2443_GPG15_CF_PWR (0x03 << 30)
874 900
875#define S3C2410_GPG_PUPDIS(x) (1<<(x)) 901#define S3C2410_GPG_PUPDIS(x) (1<<(x))
876 902
diff --git a/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h b/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
new file mode 100644
index 000000000000..ff0536d2de42
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/regs-s3c2443-clock.h
@@ -0,0 +1,194 @@
1/* linux/include/asm-arm/arch-s3c2410/regs-clock.h
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * S3C2443 clock register definitions
12*/
13
14#ifndef __ASM_ARM_REGS_S3C2443_CLOCK
15#define __ASM_ARM_REGS_S3C2443_CLOCK
16
17#define S3C2443_CLKREG(x) ((x) + S3C24XX_VA_CLKPWR)
18
19#define S3C2443_PLLCON_MDIVSHIFT 16
20#define S3C2443_PLLCON_PDIVSHIFT 8
21#define S3C2443_PLLCON_SDIVSHIFT 0
22#define S3C2443_PLLCON_MDIVMASK ((1<<(1+(23-16)))-1)
23#define S3C2443_PLLCON_PDIVMASK ((1<<(1+(9-8)))-1)
24#define S3C2443_PLLCON_SDIVMASK (3)
25
26#define S3C2443_MPLLCON S3C2443_CLKREG(0x10)
27#define S3C2443_EPLLCON S3C2443_CLKREG(0x18)
28#define S3C2443_CLKSRC S3C2443_CLKREG(0x20)
29#define S3C2443_CLKDIV0 S3C2443_CLKREG(0x24)
30#define S3C2443_CLKDIV1 S3C2443_CLKREG(0x28)
31#define S3C2443_HCLKCON S3C2443_CLKREG(0x30)
32#define S3C2443_PCLKCON S3C2443_CLKREG(0x34)
33#define S3C2443_SCLKCON S3C2443_CLKREG(0x38)
34#define S3C2443_PWRMODE S3C2443_CLKREG(0x40)
35#define S3C2443_SWRST S3C2443_CLKREG(0x44)
36#define S3C2443_BUSPRI0 S3C2443_CLKREG(0x50)
37#define S3C2443_SYSID S3C2443_CLKREG(0x5C)
38#define S3C2443_PWRCFG S3C2443_CLKREG(0x60)
39#define S3C2443_RSTCON S3C2443_CLKREG(0x64)
40
41#define S3C2443_SWRST_RESET (0x533c2443)
42
43#define S3C2443_PLLCON_OFF (1<<24)
44
45#define S3C2443_CLKSRC_I2S_EXT (1<<14)
46#define S3C2443_CLKSRC_I2S_EPLLDIV (0<<14)
47#define S3C2443_CLKSRC_I2S_EPLLREF (2<<14)
48#define S3C2443_CLKSRC_I2S_EPLLREF3 (3<<14)
49#define S3C2443_CLKSRC_I2S_MASK (3<<14)
50
51#define S3C2443_CLKSRC_EPLLREF_XTAL (2<<8)
52#define S3C2443_CLKSRC_EPLLREF_EXTCLK (3<<8)
53#define S3C2443_CLKSRC_EPLLREF_MPLLREF (0<<8)
54#define S3C2443_CLKSRC_EPLLREF_MPLLREF2 (1<<8)
55#define S3C2443_CLKSRC_EPLLREF_MASK (3<<8)
56
57#define S3C2443_CLKSRC_ESYSCLK_EPLL (1<<6)
58#define S3C2443_CLKSRC_MSYSCLK_MPLL (1<<4)
59#define S3C2443_CLKSRC_EXTCLK_DIV (1<<3)
60
61#define S3C2443_CLKDIV0_DVS (1<<13)
62#define S3C2443_CLKDIV0_HALF_HCLK (1<<3)
63#define S3C2443_CLKDIV0_HALF_PCLK (1<<2)
64
65#define S3C2443_CLKDIV0_HCLKDIV_MASK (3<<0)
66
67#define S3C2443_CLKDIV0_EXTDIV_MASK (3<<6)
68#define S3C2443_CLKDIV0_EXTDIV_SHIFT (6)
69
70#define S3C2443_CLKDIV0_PREDIV_MASK (3<<4)
71#define S3C2443_CLKDIV0_PREDIV_SHIFT (4)
72
73#define S3C2443_CLKDIV0_ARMDIV_MASK (15<<9)
74#define S3C2443_CLKDIV0_ARMDIV_SHIFT (9)
75#define S3C2443_CLKDIV0_ARMDIV_1 (0<<9)
76#define S3C2443_CLKDIV0_ARMDIV_2 (8<<9)
77#define S3C2443_CLKDIV0_ARMDIV_3 (2<<9)
78#define S3C2443_CLKDIV0_ARMDIV_4 (9<<9)
79#define S3C2443_CLKDIV0_ARMDIV_6 (10<<9)
80#define S3C2443_CLKDIV0_ARMDIV_8 (11<<9)
81#define S3C2443_CLKDIV0_ARMDIV_12 (13<<9)
82#define S3C2443_CLKDIV0_ARMDIV_16 (15<<9)
83
84/* S3C2443_CLKDIV1 */
85
86#define S3C2443_CLKDIV1_CAMDIV_MASK (15<<26)
87#define S3C2443_CLKDIV1_CAMDIV_SHIFT (26)
88
89#define S3C2443_CLKDIV1_HSSPIDIV_MASK (3<<24)
90#define S3C2443_CLKDIV1_HSSPIDIV_SHIFT (24)
91
92#define S3C2443_CLKDIV1_DISPDIV_MASK (0xff<<16)
93#define S3C2443_CLKDIV1_DISPDIV_SHIFT (16)
94
95#define S3C2443_CLKDIV1_I2SDIV_MASK (15<<12)
96#define S3C2443_CLKDIV1_I2SDIV_SHIFT (12)
97
98#define S3C2443_CLKDIV1_UARTDIV_MASK (15<<8)
99#define S3C2443_CLKDIV1_UARTDIV_SHIFT (8)
100
101#define S3C2443_CLKDIV1_HSMMCDIV_MASK (3<<6)
102#define S3C2443_CLKDIV1_HSMMCDIV_SHIFT (6)
103
104#define S3C2443_CLKDIV1_USBHOSTDIV_MASK (3<<4)
105#define S3C2443_CLKDIV1_USBHOSTDIV_SHIFT (4)
106
107#define S3C2443_CLKCON_NAND
108
109#define S3C2443_HCLKCON_DMA0 (1<<0)
110#define S3C2443_HCLKCON_DMA1 (1<<1)
111#define S3C2443_HCLKCON_DMA2 (1<<2)
112#define S3C2443_HCLKCON_DMA3 (1<<3)
113#define S3C2443_HCLKCON_DMA4 (1<<4)
114#define S3C2443_HCLKCON_DMA5 (1<<5)
115#define S3C2443_HCLKCON_CAMIF (1<<8)
116#define S3C2443_HCLKCON_DISP (1<<9)
117#define S3C2443_HCLKCON_LCDC (1<<10)
118#define S3C2443_HCLKCON_USBH (1<<11)
119#define S3C2443_HCLKCON_USBD (1<<12)
120#define S3C2443_HCLKCON_HSMMC (1<<16)
121#define S3C2443_HCLKCON_CFC (1<<17)
122#define S3C2443_HCLKCON_SSMC (1<<18)
123#define S3C2443_HCLKCON_DRAMC (1<<19)
124
125#define S3C2443_PCLKCON_UART0 (1<<0)
126#define S3C2443_PCLKCON_UART1 (1<<1)
127#define S3C2443_PCLKCON_UART2 (1<<2)
128#define S3C2443_PCLKCON_UART3 (1<<3)
129#define S3C2443_PCLKCON_IIC (1<<4)
130#define S3C2443_PCLKCON_SDI (1<<5)
131#define S3C2443_PCLKCON_ADC (1<<7)
132#define S3C2443_PCLKCON_IIS (1<<9)
133#define S3C2443_PCLKCON_PWMT (1<<10)
134#define S3C2443_PCLKCON_WDT (1<<11)
135#define S3C2443_PCLKCON_RTC (1<<12)
136#define S3C2443_PCLKCON_GPIO (1<<13)
137#define S3C2443_PCLKCON_SPI0 (1<<14)
138#define S3C2443_PCLKCON_SPI1 (1<<15)
139
140#define S3C2443_SCLKCON_DDRCLK (1<<16)
141#define S3C2443_SCLKCON_SSMCCLK (1<<15)
142#define S3C2443_SCLKCON_HSSPICLK (1<<14)
143#define S3C2443_SCLKCON_HSMMCCLK_EXT (1<<13)
144#define S3C2443_SCLKCON_HSMMCCLK_EPLL (1<<12)
145#define S3C2443_SCLKCON_CAMCLK (1<<11)
146#define S3C2443_SCLKCON_DISPCLK (1<<10)
147#define S3C2443_SCLKCON_I2SCLK (1<<9)
148#define S3C2443_SCLKCON_UARTCLK (1<<8)
149#define S3C2443_SCLKCON_USBHOST (1<<1)
150
151#include <asm/div64.h>
152
153static inline unsigned int
154s3c2443_get_mpll(unsigned int pllval, unsigned int baseclk)
155{
156 unsigned int mdiv, pdiv, sdiv;
157 uint64_t fvco;
158
159 mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
160 pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
161 sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
162
163 mdiv &= S3C2443_PLLCON_MDIVMASK;
164 pdiv &= S3C2443_PLLCON_PDIVMASK;
165 sdiv &= S3C2443_PLLCON_SDIVMASK;
166
167 fvco = (uint64_t)baseclk * (2 * (mdiv + 8));
168 do_div(fvco, pdiv << sdiv);
169
170 return (unsigned int)fvco;
171}
172
173static inline unsigned int
174s3c2443_get_epll(unsigned int pllval, unsigned int baseclk)
175{
176 unsigned int mdiv, pdiv, sdiv;
177 uint64_t fvco;
178
179 mdiv = pllval >> S3C2443_PLLCON_MDIVSHIFT;
180 pdiv = pllval >> S3C2443_PLLCON_PDIVSHIFT;
181 sdiv = pllval >> S3C2443_PLLCON_SDIVSHIFT;
182
183 mdiv &= S3C2443_PLLCON_MDIVMASK;
184 pdiv &= S3C2443_PLLCON_PDIVMASK;
185 sdiv &= S3C2443_PLLCON_SDIVMASK;
186
187 fvco = (uint64_t)baseclk * (mdiv + 8);
188 do_div(fvco, (pdiv + 2) << sdiv);
189
190 return (unsigned int)fvco;
191}
192
193#endif /* __ASM_ARM_REGS_S3C2443_CLOCK */
194
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 46f52401d132..8946702a87f5 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -35,10 +35,12 @@
35#define S3C24XX_VA_UART0 (S3C24XX_VA_UART) 35#define S3C24XX_VA_UART0 (S3C24XX_VA_UART)
36#define S3C24XX_VA_UART1 (S3C24XX_VA_UART + 0x4000 ) 36#define S3C24XX_VA_UART1 (S3C24XX_VA_UART + 0x4000 )
37#define S3C24XX_VA_UART2 (S3C24XX_VA_UART + 0x8000 ) 37#define S3C24XX_VA_UART2 (S3C24XX_VA_UART + 0x8000 )
38#define S3C24XX_VA_UART3 (S3C24XX_VA_UART + 0xC000 )
38 39
39#define S3C2410_PA_UART0 (S3C24XX_PA_UART) 40#define S3C2410_PA_UART0 (S3C24XX_PA_UART)
40#define S3C2410_PA_UART1 (S3C24XX_PA_UART + 0x4000 ) 41#define S3C2410_PA_UART1 (S3C24XX_PA_UART + 0x4000 )
41#define S3C2410_PA_UART2 (S3C24XX_PA_UART + 0x8000 ) 42#define S3C2410_PA_UART2 (S3C24XX_PA_UART + 0x8000 )
43#define S3C2443_PA_UART3 (S3C24XX_PA_UART + 0xC000 )
42 44
43#define S3C2410_URXH (0x24) 45#define S3C2410_URXH (0x24)
44#define S3C2410_UTXH (0x20) 46#define S3C2410_UTXH (0x20)
@@ -73,6 +75,8 @@
73#define S3C2440_UCON_UCLK (1<<10) 75#define S3C2440_UCON_UCLK (1<<10)
74#define S3C2440_UCON_PCLK2 (2<<10) 76#define S3C2440_UCON_PCLK2 (2<<10)
75#define S3C2440_UCON_FCLK (3<<10) 77#define S3C2440_UCON_FCLK (3<<10)
78#define S3C2443_UCON_EPLL (3<<10)
79
76#define S3C2440_UCON2_FCLK_EN (1<<15) 80#define S3C2440_UCON2_FCLK_EN (1<<15)
77#define S3C2440_UCON0_DIVMASK (15 << 12) 81#define S3C2440_UCON0_DIVMASK (15 << 12)
78#define S3C2440_UCON1_DIVMASK (15 << 12) 82#define S3C2440_UCON1_DIVMASK (15 << 12)
@@ -93,6 +97,8 @@
93#define S3C2410_UCON_TXIRQMODE (1<<2) 97#define S3C2410_UCON_TXIRQMODE (1<<2)
94#define S3C2410_UCON_RXIRQMODE (1<<0) 98#define S3C2410_UCON_RXIRQMODE (1<<0)
95#define S3C2410_UCON_RXFIFO_TOI (1<<7) 99#define S3C2410_UCON_RXFIFO_TOI (1<<7)
100#define S3C2443_UCON_RXERR_IRQEN (1<<6)
101#define S3C2443_UCON_LOOPBACK (1<<5)
96 102
97#define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \ 103#define S3C2410_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
98 S3C2410_UCON_RXILEVEL | \ 104 S3C2410_UCON_RXILEVEL | \
@@ -127,7 +133,7 @@
127#define S3C2410_UMCOM_AFC (1<<4) 133#define S3C2410_UMCOM_AFC (1<<4)
128#define S3C2410_UMCOM_RTS_LOW (1<<0) 134#define S3C2410_UMCOM_RTS_LOW (1<<0)
129 135
130#define S3C2412_UMCON_AFC_63 (0<<5) 136#define S3C2412_UMCON_AFC_63 (0<<5) /* same as s3c2443 */
131#define S3C2412_UMCON_AFC_56 (1<<5) 137#define S3C2412_UMCON_AFC_56 (1<<5)
132#define S3C2412_UMCON_AFC_48 (2<<5) 138#define S3C2412_UMCON_AFC_48 (2<<5)
133#define S3C2412_UMCON_AFC_40 (3<<5) 139#define S3C2412_UMCON_AFC_40 (3<<5)
@@ -143,6 +149,7 @@
143#define S3C2410_UFSTAT_RXMASK (15<<0) 149#define S3C2410_UFSTAT_RXMASK (15<<0)
144#define S3C2410_UFSTAT_RXSHIFT (0) 150#define S3C2410_UFSTAT_RXSHIFT (0)
145 151
152/* UFSTAT S3C2443 same as S3C2440 */
146#define S3C2440_UFSTAT_TXFULL (1<<14) 153#define S3C2440_UFSTAT_TXFULL (1<<14)
147#define S3C2440_UFSTAT_RXFULL (1<<6) 154#define S3C2440_UFSTAT_RXFULL (1<<6)
148#define S3C2440_UFSTAT_TXSHIFT (8) 155#define S3C2440_UFSTAT_TXSHIFT (8)
@@ -157,6 +164,8 @@
157#define S3C2410_UERSTAT_OVERRUN (1<<0) 164#define S3C2410_UERSTAT_OVERRUN (1<<0)
158#define S3C2410_UERSTAT_FRAME (1<<2) 165#define S3C2410_UERSTAT_FRAME (1<<2)
159#define S3C2410_UERSTAT_BREAK (1<<3) 166#define S3C2410_UERSTAT_BREAK (1<<3)
167#define S3C2443_UERSTAT_PARITY (1<<1)
168
160#define S3C2410_UERSTAT_ANY (S3C2410_UERSTAT_OVERRUN | \ 169#define S3C2410_UERSTAT_ANY (S3C2410_UERSTAT_OVERRUN | \
161 S3C2410_UERSTAT_FRAME | \ 170 S3C2410_UERSTAT_FRAME | \
162 S3C2410_UERSTAT_BREAK) 171 S3C2410_UERSTAT_BREAK)
@@ -164,6 +173,8 @@
164#define S3C2410_UMSTAT_CTS (1<<0) 173#define S3C2410_UMSTAT_CTS (1<<0)
165#define S3C2410_UMSTAT_DeltaCTS (1<<2) 174#define S3C2410_UMSTAT_DeltaCTS (1<<2)
166 175
176#define S3C2443_DIVSLOT (0x2C)
177
167#ifndef __ASSEMBLY__ 178#ifndef __ASSEMBLY__
168 179
169/* struct s3c24xx_uart_clksrc 180/* struct s3c24xx_uart_clksrc
diff --git a/include/asm-arm/arch-s3c2410/reset.h b/include/asm-arm/arch-s3c2410/reset.h
new file mode 100644
index 000000000000..4f866cdecab0
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/reset.h
@@ -0,0 +1,22 @@
1/* linux/include/asm-arm/arch-s3c2410/reset.h
2 *
3 * Copyright (c) 2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
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 version 2 as
9 * published by the Free Software Foundation.
10 *
11 * S3C2410 CPU reset controls
12*/
13
14#ifndef __ASM_ARCH_RESET_H
15#define __ASM_ARCH_RESET_H __FILE__
16
17/* This allows the over-ride of the default reset code
18*/
19
20extern void (*s3c24xx_reset_hook)(void);
21
22#endif /* __ASM_ARCH_RESET_H */
diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
index ecf250db45fb..1c74ef17da33 100644
--- a/include/asm-arm/arch-s3c2410/system.h
+++ b/include/asm-arm/arch-s3c2410/system.h
@@ -15,15 +15,16 @@
15 15
16#include <asm/arch/map.h> 16#include <asm/arch/map.h>
17#include <asm/arch/idle.h> 17#include <asm/arch/idle.h>
18#include <asm/arch/reset.h>
18 19
19#include <asm/arch/regs-watchdog.h> 20#include <asm/arch/regs-watchdog.h>
20#include <asm/arch/regs-clock.h> 21#include <asm/arch/regs-clock.h>
21 22
22void (*s3c24xx_idle)(void); 23void (*s3c24xx_idle)(void);
24void (*s3c24xx_reset_hook)(void);
23 25
24void s3c24xx_default_idle(void) 26void s3c24xx_default_idle(void)
25{ 27{
26 void __iomem *reg = S3C2410_CLKCON;
27 unsigned long tmp; 28 unsigned long tmp;
28 int i; 29 int i;
29 30
@@ -33,16 +34,18 @@ void s3c24xx_default_idle(void)
33 34
34 /* Warning: going into idle state upsets jtag scanning */ 35 /* Warning: going into idle state upsets jtag scanning */
35 36
36 __raw_writel(__raw_readl(reg) | (1<<2), reg); 37 __raw_writel(__raw_readl(S3C2410_CLKCON) | S3C2410_CLKCON_IDLE,
38 S3C2410_CLKCON);
37 39
38 /* the samsung port seems to do a loop and then unset idle.. */ 40 /* the samsung port seems to do a loop and then unset idle.. */
39 for (i = 0; i < 50; i++) { 41 for (i = 0; i < 50; i++) {
40 tmp += __raw_readl(reg); /* ensure loop not optimised out */ 42 tmp += __raw_readl(S3C2410_CLKCON); /* ensure loop not optimised out */
41 } 43 }
42 44
43 /* this bit is not cleared on re-start... */ 45 /* this bit is not cleared on re-start... */
44 46
45 __raw_writel(__raw_readl(reg) & ~(1<<2), reg); 47 __raw_writel(__raw_readl(S3C2410_CLKCON) & ~S3C2410_CLKCON_IDLE,
48 S3C2410_CLKCON);
46} 49}
47 50
48static void arch_idle(void) 51static void arch_idle(void)
@@ -53,7 +56,6 @@ static void arch_idle(void)
53 s3c24xx_default_idle(); 56 s3c24xx_default_idle();
54} 57}
55 58
56
57static void 59static void
58arch_reset(char mode) 60arch_reset(char mode)
59{ 61{
@@ -61,6 +63,9 @@ arch_reset(char mode)
61 cpu_reset(0); 63 cpu_reset(0);
62 } 64 }
63 65
66 if (s3c24xx_reset_hook)
67 s3c24xx_reset_hook();
68
64 printk("arch_reset: attempting watchdog reset\n"); 69 printk("arch_reset: attempting watchdog reset\n");
65 70
66 __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */ 71 __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */
diff --git a/include/asm-arm/arch-s3c2410/udc.h b/include/asm-arm/arch-s3c2410/udc.h
new file mode 100644
index 000000000000..e59ec339d614
--- /dev/null
+++ b/include/asm-arm/arch-s3c2410/udc.h
@@ -0,0 +1,36 @@
1/* linux/include/asm/arch-s3c2410/udc.h
2 *
3 * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
4 *
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 * Changelog:
12 * 14-Mar-2005 RTP Created file
13 * 02-Aug-2005 RTP File rename
14 * 07-Sep-2005 BJD Minor cleanups, changed cmd to enum
15 * 18-Jan-2007 HMW Add per-platform vbus_draw function
16*/
17
18#ifndef __ASM_ARM_ARCH_UDC_H
19#define __ASM_ARM_ARCH_UDC_H
20
21enum s3c2410_udc_cmd_e {
22 S3C2410_UDC_P_ENABLE = 1, /* Pull-up enable */
23 S3C2410_UDC_P_DISABLE = 2, /* Pull-up disable */
24 S3C2410_UDC_P_RESET = 3, /* UDC reset, in case of */
25};
26
27struct s3c2410_udc_mach_info {
28 void (*udc_command)(enum s3c2410_udc_cmd_e);
29 void (*vbus_draw)(unsigned int ma);
30 unsigned int vbus_pin;
31 unsigned char vbus_pin_inverted;
32};
33
34extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
35
36#endif /* __ASM_ARM_ARCH_UDC_H */
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 5f531ea03059..afad32c76e6c 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -185,9 +185,15 @@ struct cpu_cache_fns {
185 void (*coherent_user_range)(unsigned long, unsigned long); 185 void (*coherent_user_range)(unsigned long, unsigned long);
186 void (*flush_kern_dcache_page)(void *); 186 void (*flush_kern_dcache_page)(void *);
187 187
188 void (*dma_inv_range)(unsigned long, unsigned long); 188 void (*dma_inv_range)(const void *, const void *);
189 void (*dma_clean_range)(unsigned long, unsigned long); 189 void (*dma_clean_range)(const void *, const void *);
190 void (*dma_flush_range)(unsigned long, unsigned long); 190 void (*dma_flush_range)(const void *, const void *);
191};
192
193struct outer_cache_fns {
194 void (*inv_range)(unsigned long, unsigned long);
195 void (*clean_range)(unsigned long, unsigned long);
196 void (*flush_range)(unsigned long, unsigned long);
191}; 197};
192 198
193/* 199/*
@@ -240,9 +246,40 @@ extern void __cpuc_flush_dcache_page(void *);
240#define dmac_clean_range __glue(_CACHE,_dma_clean_range) 246#define dmac_clean_range __glue(_CACHE,_dma_clean_range)
241#define dmac_flush_range __glue(_CACHE,_dma_flush_range) 247#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
242 248
243extern void dmac_inv_range(unsigned long, unsigned long); 249extern void dmac_inv_range(const void *, const void *);
244extern void dmac_clean_range(unsigned long, unsigned long); 250extern void dmac_clean_range(const void *, const void *);
245extern void dmac_flush_range(unsigned long, unsigned long); 251extern void dmac_flush_range(const void *, const void *);
252
253#endif
254
255#ifdef CONFIG_OUTER_CACHE
256
257extern struct outer_cache_fns outer_cache;
258
259static inline void outer_inv_range(unsigned long start, unsigned long end)
260{
261 if (outer_cache.inv_range)
262 outer_cache.inv_range(start, end);
263}
264static inline void outer_clean_range(unsigned long start, unsigned long end)
265{
266 if (outer_cache.clean_range)
267 outer_cache.clean_range(start, end);
268}
269static inline void outer_flush_range(unsigned long start, unsigned long end)
270{
271 if (outer_cache.flush_range)
272 outer_cache.flush_range(start, end);
273}
274
275#else
276
277static inline void outer_inv_range(unsigned long start, unsigned long end)
278{ }
279static inline void outer_clean_range(unsigned long start, unsigned long end)
280{ }
281static inline void outer_flush_range(unsigned long start, unsigned long end)
282{ }
246 283
247#endif 284#endif
248 285
diff --git a/include/asm-arm/device.h b/include/asm-arm/device.h
index d8f9872b0e2d..c61642b40603 100644
--- a/include/asm-arm/device.h
+++ b/include/asm-arm/device.h
@@ -3,5 +3,13 @@
3 * 3 *
4 * This file is released under the GPLv2 4 * This file is released under the GPLv2
5 */ 5 */
6#include <asm-generic/device.h> 6#ifndef ASMARM_DEVICE_H
7#define ASMARM_DEVICE_H
7 8
9struct dev_archdata {
10#ifdef CONFIG_DMABOUNCE
11 struct dmabounce_device_info *dmabounce;
12#endif
13};
14
15#endif
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index 9bc46b486afb..abfb75b654c7 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -17,7 +17,7 @@
17 * platforms with CONFIG_DMABOUNCE. 17 * platforms with CONFIG_DMABOUNCE.
18 * Use the driver DMA support - see dma-mapping.h (dma_sync_*) 18 * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
19 */ 19 */
20extern void consistent_sync(void *kaddr, size_t size, int rw); 20extern void consistent_sync(const void *kaddr, size_t size, int rw);
21 21
22/* 22/*
23 * Return whether the given device DMA address mask can be supported 23 * Return whether the given device DMA address mask can be supported
@@ -61,6 +61,22 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
61 return dma_addr == ~0; 61 return dma_addr == ~0;
62} 62}
63 63
64/*
65 * Dummy noncoherent implementation. We don't provide a dma_cache_sync
66 * function so drivers using this API are highlighted with build warnings.
67 */
68static inline void *
69dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
70{
71 return NULL;
72}
73
74static inline void
75dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
76 dma_addr_t handle)
77{
78}
79
64/** 80/**
65 * dma_alloc_coherent - allocate consistent memory for DMA 81 * dma_alloc_coherent - allocate consistent memory for DMA
66 * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices 82 * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/include/asm-arm/domain.h b/include/asm-arm/domain.h
index 4c2885abbe6c..3c12a7625304 100644
--- a/include/asm-arm/domain.h
+++ b/include/asm-arm/domain.h
@@ -57,6 +57,7 @@
57 __asm__ __volatile__( \ 57 __asm__ __volatile__( \
58 "mcr p15, 0, %0, c3, c0 @ set domain" \ 58 "mcr p15, 0, %0, c3, c0 @ set domain" \
59 : : "r" (x)); \ 59 : : "r" (x)); \
60 isb(); \
60 } while (0) 61 } while (0)
61 62
62#define modify_domain(dom,type) \ 63#define modify_domain(dom,type) \
diff --git a/include/asm-arm/hardware/arm_scu.h b/include/asm-arm/hardware/arm_scu.h
index 9903f60c84b7..7d28eb5a1758 100644
--- a/include/asm-arm/hardware/arm_scu.h
+++ b/include/asm-arm/hardware/arm_scu.h
@@ -1,6 +1,8 @@
1#ifndef ASMARM_HARDWARE_ARM_SCU_H 1#ifndef ASMARM_HARDWARE_ARM_SCU_H
2#define ASMARM_HARDWARE_ARM_SCU_H 2#define ASMARM_HARDWARE_ARM_SCU_H
3 3
4#include <asm/arch/scu.h>
5
4/* 6/*
5 * SCU registers 7 * SCU registers
6 */ 8 */
diff --git a/include/asm-arm/hardware/cache-l2x0.h b/include/asm-arm/hardware/cache-l2x0.h
new file mode 100644
index 000000000000..54029a740396
--- /dev/null
+++ b/include/asm-arm/hardware/cache-l2x0.h
@@ -0,0 +1,56 @@
1/*
2 * include/asm-arm/hardware/cache-l2x0.h
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
20#ifndef __ASM_ARM_HARDWARE_L2X0_H
21#define __ASM_ARM_HARDWARE_L2X0_H
22
23#define L2X0_CACHE_ID 0x000
24#define L2X0_CACHE_TYPE 0x004
25#define L2X0_CTRL 0x100
26#define L2X0_AUX_CTRL 0x104
27#define L2X0_EVENT_CNT_CTRL 0x200
28#define L2X0_EVENT_CNT1_CFG 0x204
29#define L2X0_EVENT_CNT0_CFG 0x208
30#define L2X0_EVENT_CNT1_VAL 0x20C
31#define L2X0_EVENT_CNT0_VAL 0x210
32#define L2X0_INTR_MASK 0x214
33#define L2X0_MASKED_INTR_STAT 0x218
34#define L2X0_RAW_INTR_STAT 0x21C
35#define L2X0_INTR_CLEAR 0x220
36#define L2X0_CACHE_SYNC 0x730
37#define L2X0_INV_LINE_PA 0x770
38#define L2X0_INV_WAY 0x77C
39#define L2X0_CLEAN_LINE_PA 0x7B0
40#define L2X0_CLEAN_LINE_IDX 0x7B8
41#define L2X0_CLEAN_WAY 0x7BC
42#define L2X0_CLEAN_INV_LINE_PA 0x7F0
43#define L2X0_CLEAN_INV_LINE_IDX 0x7F8
44#define L2X0_CLEAN_INV_WAY 0x7FC
45#define L2X0_LOCKDOWN_WAY_D 0x900
46#define L2X0_LOCKDOWN_WAY_I 0x904
47#define L2X0_TEST_OPERATION 0xF00
48#define L2X0_LINE_DATA 0xF10
49#define L2X0_LINE_TAG 0xF30
50#define L2X0_DEBUG_CTRL 0xF40
51
52#ifndef __ASSEMBLY__
53extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
54#endif
55
56#endif
diff --git a/include/asm-arm/hardware/gic.h b/include/asm-arm/hardware/gic.h
index 3fa5eb70f64e..966e428ad32c 100644
--- a/include/asm-arm/hardware/gic.h
+++ b/include/asm-arm/hardware/gic.h
@@ -33,8 +33,9 @@
33#define GIC_DIST_SOFTINT 0xf00 33#define GIC_DIST_SOFTINT 0xf00
34 34
35#ifndef __ASSEMBLY__ 35#ifndef __ASSEMBLY__
36void gic_dist_init(void __iomem *base); 36void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
37void gic_cpu_init(void __iomem *base); 37void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
38void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
38void gic_raise_softirq(cpumask_t cpumask, unsigned int irq); 39void gic_raise_softirq(cpumask_t cpumask, unsigned int irq);
39#endif 40#endif
40 41
diff --git a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h
index 6aa0a5b75b69..61b1d05c7df7 100644
--- a/include/asm-arm/hardware/sa1111.h
+++ b/include/asm-arm/hardware/sa1111.h
@@ -29,6 +29,9 @@
29#define _SA1111(x) ((x) + sa1111->resource.start) 29#define _SA1111(x) ((x) + sa1111->resource.start)
30#endif 30#endif
31 31
32#define sa1111_writel(val,addr) __raw_writel(val, addr)
33#define sa1111_readl(addr) __raw_readl(addr)
34
32/* 35/*
33 * 26 bits of the SA-1110 address bus are available to the SA-1111. 36 * 26 bits of the SA-1110 address bus are available to the SA-1111.
34 * Use these when feeding target addresses to the DMA engines. 37 * Use these when feeding target addresses to the DMA engines.
@@ -45,14 +48,6 @@
45#define SA1111_SAC_DMA_MIN_XFER (0x800) 48#define SA1111_SAC_DMA_MIN_XFER (0x800)
46 49
47/* 50/*
48 * SA1111 register definitions.
49 */
50#define __CCREG(x) __REGP(SA1111_VBASE + (x))
51
52#define sa1111_writel(val,addr) __raw_writel(val, addr)
53#define sa1111_readl(addr) __raw_readl(addr)
54
55/*
56 * System Bus Interface (SBI) 51 * System Bus Interface (SBI)
57 * 52 *
58 * Registers 53 * Registers
@@ -194,55 +189,37 @@
194 * SADR Serial Audio Data Register (16 x 32-bit) 189 * SADR Serial Audio Data Register (16 x 32-bit)
195 */ 190 */
196 191
197#define _SACR0 _SA1111( 0x0600 ) 192#define SA1111_SERAUDIO 0x0600
198#define _SACR1 _SA1111( 0x0604 ) 193
199#define _SACR2 _SA1111( 0x0608 ) 194/*
200#define _SASR0 _SA1111( 0x060c ) 195 * These are offsets from the above base.
201#define _SASR1 _SA1111( 0x0610 ) 196 */
202#define _SASCR _SA1111( 0x0618 ) 197#define SA1111_SACR0 0x00
203#define _L3_CAR _SA1111( 0x061c ) 198#define SA1111_SACR1 0x04
204#define _L3_CDR _SA1111( 0x0620 ) 199#define SA1111_SACR2 0x08
205#define _ACCAR _SA1111( 0x0624 ) 200#define SA1111_SASR0 0x0c
206#define _ACCDR _SA1111( 0x0628 ) 201#define SA1111_SASR1 0x10
207#define _ACSAR _SA1111( 0x062c ) 202#define SA1111_SASCR 0x18
208#define _ACSDR _SA1111( 0x0630 ) 203#define SA1111_L3_CAR 0x1c
209#define _SADTCS _SA1111( 0x0634 ) 204#define SA1111_L3_CDR 0x20
210#define _SADTSA _SA1111( 0x0638 ) 205#define SA1111_ACCAR 0x24
211#define _SADTCA _SA1111( 0x063c ) 206#define SA1111_ACCDR 0x28
212#define _SADTSB _SA1111( 0x0640 ) 207#define SA1111_ACSAR 0x2c
213#define _SADTCB _SA1111( 0x0644 ) 208#define SA1111_ACSDR 0x30
214#define _SADRCS _SA1111( 0x0648 ) 209#define SA1111_SADTCS 0x34
215#define _SADRSA _SA1111( 0x064c ) 210#define SA1111_SADTSA 0x38
216#define _SADRCA _SA1111( 0x0650 ) 211#define SA1111_SADTCA 0x3c
217#define _SADRSB _SA1111( 0x0654 ) 212#define SA1111_SADTSB 0x40
218#define _SADRCB _SA1111( 0x0658 ) 213#define SA1111_SADTCB 0x44
219#define _SAITR _SA1111( 0x065c ) 214#define SA1111_SADRCS 0x48
220#define _SADR _SA1111( 0x0680 ) 215#define SA1111_SADRSA 0x4c
221 216#define SA1111_SADRCA 0x50
222#define SACR0 __CCREG(0x0600) 217#define SA1111_SADRSB 0x54
223#define SACR1 __CCREG(0x0604) 218#define SA1111_SADRCB 0x58
224#define SACR2 __CCREG(0x0608) 219#define SA1111_SAITR 0x5c
225#define SASR0 __CCREG(0x060c) 220#define SA1111_SADR 0x80
226#define SASR1 __CCREG(0x0610) 221
227#define SASCR __CCREG(0x0618) 222#ifndef CONFIG_ARCH_PXA
228#define L3_CAR __CCREG(0x061c)
229#define L3_CDR __CCREG(0x0620)
230#define ACCAR __CCREG(0x0624)
231#define ACCDR __CCREG(0x0628)
232#define ACSAR __CCREG(0x062c)
233#define ACSDR __CCREG(0x0630)
234#define SADTCS __CCREG(0x0634)
235#define SADTSA __CCREG(0x0638)
236#define SADTCA __CCREG(0x063c)
237#define SADTSB __CCREG(0x0640)
238#define SADTCB __CCREG(0x0644)
239#define SADRCS __CCREG(0x0648)
240#define SADRSA __CCREG(0x064c)
241#define SADRCA __CCREG(0x0650)
242#define SADRSB __CCREG(0x0654)
243#define SADRCB __CCREG(0x0658)
244#define SAITR __CCREG(0x065c)
245#define SADR __CCREG(0x0680)
246 223
247#define SACR0_ENB (1<<0) 224#define SACR0_ENB (1<<0)
248#define SACR0_BCKD (1<<2) 225#define SACR0_BCKD (1<<2)
@@ -330,6 +307,8 @@
330#define SAITR_RDBDA (1<<10) 307#define SAITR_RDBDA (1<<10)
331#define SAITR_RDBDB (1<<11) 308#define SAITR_RDBDB (1<<11)
332 309
310#endif /* !CONFIG_ARCH_PXA */
311
333/* 312/*
334 * General-Purpose I/O Interface 313 * General-Purpose I/O Interface
335 * 314 *
diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
new file mode 100644
index 000000000000..8c1c6162a80c
--- /dev/null
+++ b/include/asm-arm/kexec.h
@@ -0,0 +1,30 @@
1#ifndef _ARM_KEXEC_H
2#define _ARM_KEXEC_H
3
4#ifdef CONFIG_KEXEC
5
6/* Maximum physical address we can use pages from */
7#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
8/* Maximum address we can reach in physical address mode */
9#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
10/* Maximum address we can use for the control code buffer */
11#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
12
13#define KEXEC_CONTROL_CODE_SIZE 4096
14
15#define KEXEC_ARCH KEXEC_ARCH_ARM
16
17#ifndef __ASSEMBLY__
18
19#define MAX_NOTE_BYTES 1024
20
21struct kimage;
22/* Provide a dummy definition to avoid build failures. */
23static inline void crash_setup_regs(struct pt_regs *newregs,
24 struct pt_regs *oldregs) { }
25
26#endif /* __ASSEMBLY__ */
27
28#endif /* CONFIG_KEXEC */
29
30#endif /* _ARM_KEXEC_H */
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index b8cf2d5ec304..7b2bafce21a2 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -175,19 +175,29 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
175#ifndef __ASSEMBLY__ 175#ifndef __ASSEMBLY__
176 176
177/* 177/*
178 * The following macros handle the cache and bufferable bits... 178 * The pgprot_* and protection_map entries will be fixed up in runtime
179 * to include the cachable and bufferable bits based on memory policy,
180 * as well as any architecture dependent bits like global/ASID and SMP
181 * shared mapping bits.
179 */ 182 */
180#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE 183#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE
181#define _L_PTE_READ L_PTE_USER | L_PTE_EXEC 184#define _L_PTE_READ L_PTE_USER | L_PTE_EXEC
182 185
186extern pgprot_t pgprot_user;
183extern pgprot_t pgprot_kernel; 187extern pgprot_t pgprot_kernel;
184 188
185#define PAGE_NONE __pgprot(_L_PTE_DEFAULT) 189#define PAGE_NONE pgprot_user
186#define PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ) 190#define PAGE_COPY __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
187#define PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE) 191#define PAGE_SHARED __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ | \
188#define PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ) 192 L_PTE_WRITE)
193#define PAGE_READONLY __pgprot(pgprot_val(pgprot_user) | _L_PTE_READ)
189#define PAGE_KERNEL pgprot_kernel 194#define PAGE_KERNEL pgprot_kernel
190 195
196#define __PAGE_NONE __pgprot(_L_PTE_DEFAULT)
197#define __PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
198#define __PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
199#define __PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
200
191#endif /* __ASSEMBLY__ */ 201#endif /* __ASSEMBLY__ */
192 202
193/* 203/*
@@ -198,23 +208,23 @@ extern pgprot_t pgprot_kernel;
198 * 2) If we could do execute protection, then read is implied 208 * 2) If we could do execute protection, then read is implied
199 * 3) write implies read permissions 209 * 3) write implies read permissions
200 */ 210 */
201#define __P000 PAGE_NONE 211#define __P000 __PAGE_NONE
202#define __P001 PAGE_READONLY 212#define __P001 __PAGE_READONLY
203#define __P010 PAGE_COPY 213#define __P010 __PAGE_COPY
204#define __P011 PAGE_COPY 214#define __P011 __PAGE_COPY
205#define __P100 PAGE_READONLY 215#define __P100 __PAGE_READONLY
206#define __P101 PAGE_READONLY 216#define __P101 __PAGE_READONLY
207#define __P110 PAGE_COPY 217#define __P110 __PAGE_COPY
208#define __P111 PAGE_COPY 218#define __P111 __PAGE_COPY
209 219
210#define __S000 PAGE_NONE 220#define __S000 __PAGE_NONE
211#define __S001 PAGE_READONLY 221#define __S001 __PAGE_READONLY
212#define __S010 PAGE_SHARED 222#define __S010 __PAGE_SHARED
213#define __S011 PAGE_SHARED 223#define __S011 __PAGE_SHARED
214#define __S100 PAGE_READONLY 224#define __S100 __PAGE_READONLY
215#define __S101 PAGE_READONLY 225#define __S101 __PAGE_READONLY
216#define __S110 PAGE_SHARED 226#define __S110 __PAGE_SHARED
217#define __S111 PAGE_SHARED 227#define __S111 __PAGE_SHARED
218 228
219#ifndef __ASSEMBLY__ 229#ifndef __ASSEMBLY__
220/* 230/*
diff --git a/arch/arm/mach-s3c2410/clock.h b/include/asm-arm/plat-s3c24xx/clock.h
index 7f0ea03e1d49..f6135dbb9fa9 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/include/asm-arm/plat-s3c24xx/clock.h
@@ -1,4 +1,4 @@
1/* 1/* linux/include/asm-arm/plat-s3c24xx/clock.h
2 * linux/arch/arm/mach-s3c2410/clock.h 2 * linux/arch/arm/mach-s3c2410/clock.h
3 * 3 *
4 * Copyright (c) 2004-2005 Simtec Electronics 4 * Copyright (c) 2004-2005 Simtec Electronics
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/include/asm-arm/plat-s3c24xx/common-smdk.h
index 0e3a3be330a3..58d9094c935c 100644
--- a/arch/arm/mach-s3c2410/common-smdk.h
+++ b/include/asm-arm/plat-s3c24xx/common-smdk.h
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/common-smdk.h 1/* linux/include/asm-arm/plat-s3c24xx/common-smdk.h
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>
diff --git a/arch/arm/mach-s3c2410/cpu.h b/include/asm-arm/plat-s3c24xx/cpu.h
index be42e4032a6d..15dd18810905 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/include/asm-arm/plat-s3c24xx/cpu.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/cpu.h 1/* linux/include/asm-arm/plat-s3c24xx/cpu.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>
@@ -67,3 +67,4 @@ extern struct sysdev_class s3c2410_sysclass;
67extern struct sysdev_class s3c2412_sysclass; 67extern struct sysdev_class s3c2412_sysclass;
68extern struct sysdev_class s3c2440_sysclass; 68extern struct sysdev_class s3c2440_sysclass;
69extern struct sysdev_class s3c2442_sysclass; 69extern struct sysdev_class s3c2442_sysclass;
70extern struct sysdev_class s3c2443_sysclass;
diff --git a/arch/arm/mach-s3c2410/devs.h b/include/asm-arm/plat-s3c24xx/devs.h
index 14fb0bade716..dddf485fc067 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/include/asm-arm/plat-s3c24xx/devs.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/devs.h 1/* linux/include/asm-arm/plat-s3c24xx/devs.h
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>
diff --git a/arch/arm/mach-s3c2410/dma.h b/include/asm-arm/plat-s3c24xx/dma.h
index 0ebfe0aab80b..2c59406435e5 100644
--- a/arch/arm/mach-s3c2410/dma.h
+++ b/include/asm-arm/plat-s3c24xx/dma.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/dma.h 1/* linux/include/asm-arm/plat-s3c24xx/dma.h
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>
@@ -14,6 +14,7 @@ extern struct sysdev_class dma_sysclass;
14extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; 14extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
15 15
16#define DMA_CH_VALID (1<<31) 16#define DMA_CH_VALID (1<<31)
17#define DMA_CH_NEVER (1<<30)
17 18
18struct s3c24xx_dma_addr { 19struct s3c24xx_dma_addr {
19 unsigned long from; 20 unsigned long from;
@@ -43,3 +44,34 @@ struct s3c24xx_dma_selection {
43}; 44};
44 45
45extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel); 46extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
47
48/* struct s3c24xx_dma_order_ch
49 *
50 * channel map for one of the `enum dma_ch` dma channels. the list
51 * entry contains a set of low-level channel numbers, orred with
52 * DMA_CH_VALID, which are checked in the order in the array.
53*/
54
55struct s3c24xx_dma_order_ch {
56 unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */
57 unsigned int flags; /* flags */
58};
59
60/* struct s3c24xx_dma_order
61 *
62 * information provided by either the core or the board to give the
63 * dma system a hint on how to allocate channels
64*/
65
66struct s3c24xx_dma_order {
67 struct s3c24xx_dma_order_ch channels[DMACH_MAX];
68};
69
70extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
71
72/* DMA init code, called from the cpu support code */
73
74extern int s3c2410_dma_init(void);
75
76extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
77 unsigned int stride);
diff --git a/arch/arm/mach-s3c2410/irq.h b/include/asm-arm/plat-s3c24xx/irq.h
index e5913da3b919..8af6d9579b31 100644
--- a/arch/arm/mach-s3c2410/irq.h
+++ b/include/asm-arm/plat-s3c24xx/irq.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/irq.h 1/* linux/include/asm-arm/plat-s3c24xx/irq.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/mach-s3c2410/pm.h b/include/asm-arm/plat-s3c24xx/pm.h
index ffe197a119fb..cc623667e48a 100644
--- a/arch/arm/mach-s3c2410/pm.h
+++ b/include/asm-arm/plat-s3c24xx/pm.h
@@ -1,4 +1,4 @@
1/* linux/arch/arm/mach-s3c2410/pm.h 1/* linux/include/asm-arm/plat-s3c24xx/pm.h
2 * 2 *
3 * Copyright (c) 2004 Simtec Electronics 3 * Copyright (c) 2004 Simtec Electronics
4 * Written by Ben Dooks, <ben@simtec.co.uk> 4 * Written by Ben Dooks, <ben@simtec.co.uk>
diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/include/asm-arm/plat-s3c24xx/s3c2400.h
index 8b2394e1ed40..3a5a16821af8 100644
--- a/arch/arm/mach-s3c2410/s3c2400.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2400.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/s3c2400.h 1/* linux/include/asm-arm/plat-s3c24xx/s3c2400.h
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>
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/include/asm-arm/plat-s3c24xx/s3c2410.h
index fbed084f26d0..36de0b835873 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2410.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/s3c2410.h 1/* linux/include/asm-arm/plat-s3c24xx/s3c2410.h
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>
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/include/asm-arm/plat-s3c24xx/s3c2412.h
index c6e56032a6e7..3ec97685e781 100644
--- a/arch/arm/mach-s3c2410/s3c2412.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2412.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/s3c2412.h 1/* linux/include/asm-arm/plat-s3c24xx/s3c2412.h
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>
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/include/asm-arm/plat-s3c24xx/s3c2440.h
index dcd316076c59..107853bf9481 100644
--- a/arch/arm/mach-s3c2410/s3c2440.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2440.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/s3c2440.h 1/* linux/include/asm-arm/plat-s3c24xx/s3c2440.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/mach-s3c2410/s3c2442.h b/include/asm-arm/plat-s3c24xx/s3c2442.h
index 0ae37d24866c..451a23a2092a 100644
--- a/arch/arm/mach-s3c2410/s3c2442.h
+++ b/include/asm-arm/plat-s3c24xx/s3c2442.h
@@ -1,4 +1,4 @@
1/* arch/arm/mach-s3c2410/s3c2442.h 1/* linux/include/asm-arm/plat-s3c24xx/s3c2442.h
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>
diff --git a/include/asm-arm/plat-s3c24xx/s3c2443.h b/include/asm-arm/plat-s3c24xx/s3c2443.h
new file mode 100644
index 000000000000..11d83b5c84e6
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/s3c2443.h
@@ -0,0 +1,32 @@
1/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h
2 *
3 * Copyright (c) 2004-2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for s3c2443 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_S3C2443
14
15struct s3c2410_uartcfg;
16
17extern int s3c2443_init(void);
18
19extern void s3c2443_map_io(struct map_desc *mach_desc, int size);
20
21extern void s3c2443_init_uarts(struct s3c2410_uartcfg *cfg, int no);
22
23extern void s3c2443_init_clocks(int xtal);
24
25extern int s3c2443_baseclk_add(void);
26
27#else
28#define s3c2443_init_clocks NULL
29#define s3c2443_init_uarts NULL
30#define s3c2443_map_io NULL
31#define s3c2443_init NULL
32#endif
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index aa223fc546af..f4386906b200 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -140,6 +140,40 @@ static inline int cpu_is_xsc3(void)
140#define cpu_is_xscale() 1 140#define cpu_is_xscale() 1
141#endif 141#endif
142 142
143#define UDBG_UNDEFINED (1 << 0)
144#define UDBG_SYSCALL (1 << 1)
145#define UDBG_BADABORT (1 << 2)
146#define UDBG_SEGV (1 << 3)
147#define UDBG_BUS (1 << 4)
148
149extern unsigned int user_debug;
150
151#if __LINUX_ARM_ARCH__ >= 4
152#define vectors_high() (cr_alignment & CR_V)
153#else
154#define vectors_high() (0)
155#endif
156
157#if __LINUX_ARM_ARCH__ >= 6
158#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
159 : : "r" (0) : "memory")
160#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
161 : : "r" (0) : "memory")
162#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
163 : : "r" (0) : "memory")
164#else
165#define isb() __asm__ __volatile__ ("" : : : "memory")
166#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
167 : : "r" (0) : "memory")
168#define dmb() __asm__ __volatile__ ("" : : : "memory")
169#endif
170#define mb() dmb()
171#define rmb() mb()
172#define wmb() mb()
173#define read_barrier_depends() do { } while(0)
174#define set_mb(var, value) do { var = value; mb(); } while (0)
175#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
176
143extern unsigned long cr_no_alignment; /* defined in entry-armv.S */ 177extern unsigned long cr_no_alignment; /* defined in entry-armv.S */
144extern unsigned long cr_alignment; /* defined in entry-armv.S */ 178extern unsigned long cr_alignment; /* defined in entry-armv.S */
145 179
@@ -154,6 +188,7 @@ static inline void set_cr(unsigned int val)
154{ 188{
155 asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" 189 asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR"
156 : : "r" (val) : "cc"); 190 : : "r" (val) : "cc");
191 isb();
157} 192}
158 193
159#ifndef CONFIG_SMP 194#ifndef CONFIG_SMP
@@ -176,34 +211,9 @@ static inline void set_copro_access(unsigned int val)
176{ 211{
177 asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access" 212 asm volatile("mcr p15, 0, %0, c1, c0, 2 @ set copro access"
178 : : "r" (val) : "cc"); 213 : : "r" (val) : "cc");
214 isb();
179} 215}
180 216
181#define UDBG_UNDEFINED (1 << 0)
182#define UDBG_SYSCALL (1 << 1)
183#define UDBG_BADABORT (1 << 2)
184#define UDBG_SEGV (1 << 3)
185#define UDBG_BUS (1 << 4)
186
187extern unsigned int user_debug;
188
189#if __LINUX_ARM_ARCH__ >= 4
190#define vectors_high() (cr_alignment & CR_V)
191#else
192#define vectors_high() (0)
193#endif
194
195#if __LINUX_ARM_ARCH__ >= 6
196#define mb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
197 : : "r" (0) : "memory")
198#else
199#define mb() __asm__ __volatile__ ("" : : : "memory")
200#endif
201#define rmb() mb()
202#define wmb() mb()
203#define read_barrier_depends() do { } while(0)
204#define set_mb(var, value) do { var = value; mb(); } while (0)
205#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
206
207/* 217/*
208 * switch_mm() may do a full cache flush over the context switch, 218 * switch_mm() may do a full cache flush over the context switch,
209 * so enable interrupts over the context switch to avoid high 219 * so enable interrupts over the context switch to avoid high
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index cd10a0b5f8ae..08c6991dc9c9 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -247,7 +247,7 @@ static inline void local_flush_tlb_all(void)
247 const unsigned int __tlb_flag = __cpu_tlb_flags; 247 const unsigned int __tlb_flag = __cpu_tlb_flags;
248 248
249 if (tlb_flag(TLB_WB)) 249 if (tlb_flag(TLB_WB))
250 asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); 250 dsb();
251 251
252 if (tlb_flag(TLB_V3_FULL)) 252 if (tlb_flag(TLB_V3_FULL))
253 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc"); 253 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
@@ -257,6 +257,15 @@ static inline void local_flush_tlb_all(void)
257 asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc"); 257 asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
258 if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL)) 258 if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
259 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc"); 259 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
260
261 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
262 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
263 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
264 /* flush the branch target cache */
265 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
266 dsb();
267 isb();
268 }
260} 269}
261 270
262static inline void local_flush_tlb_mm(struct mm_struct *mm) 271static inline void local_flush_tlb_mm(struct mm_struct *mm)
@@ -266,7 +275,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
266 const unsigned int __tlb_flag = __cpu_tlb_flags; 275 const unsigned int __tlb_flag = __cpu_tlb_flags;
267 276
268 if (tlb_flag(TLB_WB)) 277 if (tlb_flag(TLB_WB))
269 asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); 278 dsb();
270 279
271 if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) { 280 if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) {
272 if (tlb_flag(TLB_V3_FULL)) 281 if (tlb_flag(TLB_V3_FULL))
@@ -285,6 +294,14 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
285 asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc"); 294 asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
286 if (tlb_flag(TLB_V6_I_ASID)) 295 if (tlb_flag(TLB_V6_I_ASID))
287 asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc"); 296 asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
297
298 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
299 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
300 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
301 /* flush the branch target cache */
302 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
303 dsb();
304 }
288} 305}
289 306
290static inline void 307static inline void
@@ -296,7 +313,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
296 uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm); 313 uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
297 314
298 if (tlb_flag(TLB_WB)) 315 if (tlb_flag(TLB_WB))
299 asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero)); 316 dsb();
300 317
301 if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { 318 if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
302 if (tlb_flag(TLB_V3_PAGE)) 319 if (tlb_flag(TLB_V3_PAGE))
@@ -317,6 +334,14 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
317 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc"); 334 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
318 if (tlb_flag(TLB_V6_I_PAGE)) 335 if (tlb_flag(TLB_V6_I_PAGE))
319 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc"); 336 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
337
338 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
339 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
340 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
341 /* flush the branch target cache */
342 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
343 dsb();
344 }
320} 345}
321 346
322static inline void local_flush_tlb_kernel_page(unsigned long kaddr) 347static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
@@ -327,7 +352,7 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
327 kaddr &= PAGE_MASK; 352 kaddr &= PAGE_MASK;
328 353
329 if (tlb_flag(TLB_WB)) 354 if (tlb_flag(TLB_WB))
330 asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); 355 dsb();
331 356
332 if (tlb_flag(TLB_V3_PAGE)) 357 if (tlb_flag(TLB_V3_PAGE))
333 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc"); 358 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
@@ -347,11 +372,14 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
347 if (tlb_flag(TLB_V6_I_PAGE)) 372 if (tlb_flag(TLB_V6_I_PAGE))
348 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc"); 373 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
349 374
350 /* The ARM ARM states that the completion of a TLB maintenance 375 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
351 * operation is only guaranteed by a DSB instruction 376 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
352 */ 377 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
353 if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE)) 378 /* flush the branch target cache */
354 asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (zero) : "cc"); 379 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
380 dsb();
381 isb();
382 }
355} 383}
356 384
357/* 385/*
@@ -369,15 +397,13 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
369 */ 397 */
370static inline void flush_pmd_entry(pmd_t *pmd) 398static inline void flush_pmd_entry(pmd_t *pmd)
371{ 399{
372 const unsigned int zero = 0;
373 const unsigned int __tlb_flag = __cpu_tlb_flags; 400 const unsigned int __tlb_flag = __cpu_tlb_flags;
374 401
375 if (tlb_flag(TLB_DCLEAN)) 402 if (tlb_flag(TLB_DCLEAN))
376 asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd" 403 asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd"
377 : : "r" (pmd) : "cc"); 404 : : "r" (pmd) : "cc");
378 if (tlb_flag(TLB_WB)) 405 if (tlb_flag(TLB_WB))
379 asm("mcr p15, 0, %0, c7, c10, 4 @ flush_pmd" 406 dsb();
380 : : "r" (zero) : "cc");
381} 407}
382 408
383static inline void clean_pmd_entry(pmd_t *pmd) 409static inline void clean_pmd_entry(pmd_t *pmd)
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 97e7060000cf..0991b7bc3f78 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -372,6 +372,7 @@
372#define __NR_move_pages (__NR_SYSCALL_BASE+344) 372#define __NR_move_pages (__NR_SYSCALL_BASE+344)
373#define __NR_getcpu (__NR_SYSCALL_BASE+345) 373#define __NR_getcpu (__NR_SYSCALL_BASE+345)
374 /* 346 for epoll_pwait */ 374 /* 346 for epoll_pwait */
375#define __NR_sys_kexec_load (__NR_SYSCALL_BASE+347)
375 376
376/* 377/*
377 * The following SWIs are ARM private. 378 * The following SWIs are ARM private.
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index d02425cdd801..696e5ec63f77 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -125,6 +125,7 @@ extern struct kimage *kexec_crash_image;
125#define KEXEC_ARCH_PPC (20 << 16) 125#define KEXEC_ARCH_PPC (20 << 16)
126#define KEXEC_ARCH_PPC64 (21 << 16) 126#define KEXEC_ARCH_PPC64 (21 << 16)
127#define KEXEC_ARCH_IA_64 (50 << 16) 127#define KEXEC_ARCH_IA_64 (50 << 16)
128#define KEXEC_ARCH_ARM (40 << 16)
128#define KEXEC_ARCH_S390 (22 << 16) 129#define KEXEC_ARCH_S390 (22 << 16)
129#define KEXEC_ARCH_SH (42 << 16) 130#define KEXEC_ARCH_SH (42 << 16)
130#define KEXEC_ARCH_MIPS_LE (10 << 16) 131#define KEXEC_ARCH_MIPS_LE (10 << 16)