diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 27 | ||||
-rw-r--r-- | arch/arm/Makefile | 10 | ||||
-rw-r--r-- | arch/arm/boot/.gitignore | 2 | ||||
-rw-r--r-- | arch/arm/boot/compressed/.gitignore | 1 | ||||
-rw-r--r-- | arch/arm/common/dmabounce.c | 87 | ||||
-rw-r--r-- | arch/arm/common/gic.c | 109 | ||||
-rw-r--r-- | arch/arm/configs/at91sam9263ek_defconfig | 1184 | ||||
-rw-r--r-- | arch/arm/configs/ateb9200_defconfig | 2 | ||||
-rw-r--r-- | arch/arm/configs/csb337_defconfig | 8 | ||||
-rw-r--r-- | arch/arm/configs/csb637_defconfig | 6 | ||||
-rw-r--r-- | arch/arm/configs/kafa_defconfig | 2 | ||||
-rw-r--r-- | arch/arm/configs/s3c2410_defconfig | 142 | ||||
-rw-r--r-- | arch/arm/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/kernel/calls.S | 1 | ||||
-rw-r--r-- | arch/arm/kernel/crunch.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/ecard.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 78 | ||||
-rw-r--r-- | arch/arm/kernel/relocate_kernel.S | 74 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/Kconfig (renamed from arch/arm/mach-at91rm9200/Kconfig) | 39 | ||||
-rw-r--r-- | arch/arm/mach-at91/Makefile (renamed from arch/arm/mach-at91rm9200/Makefile) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/Makefile.boot (renamed from arch/arm/mach-at91rm9200/Makefile.boot) | 0 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91rm9200.c (renamed from arch/arm/mach-at91rm9200/at91rm9200.c) | 39 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91rm9200_devices.c (renamed from arch/arm/mach-at91rm9200/at91rm9200_devices.c) | 10 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91rm9200_time.c (renamed from arch/arm/mach-at91rm9200/at91rm9200_time.c) | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9260.c (renamed from arch/arm/mach-at91rm9200/at91sam9260.c) | 90 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9260_devices.c (renamed from arch/arm/mach-at91rm9200/at91sam9260_devices.c) | 16 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9261.c (renamed from arch/arm/mach-at91rm9200/at91sam9261.c) | 23 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9261_devices.c (renamed from arch/arm/mach-at91rm9200/at91sam9261_devices.c) | 10 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9263.c | 313 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9263_devices.c | 818 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam926x_time.c (renamed from arch/arm/mach-at91rm9200/at91sam926x_time.c) | 5 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-1arm.c (renamed from arch/arm/mach-at91rm9200/board-1arm.c) | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-carmeva.c (renamed from arch/arm/mach-at91rm9200/board-carmeva.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-csb337.c (renamed from arch/arm/mach-at91rm9200/board-csb337.c) | 43 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-csb637.c (renamed from arch/arm/mach-at91rm9200/board-csb637.c) | 41 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-dk.c (renamed from arch/arm/mach-at91rm9200/board-dk.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-eb9200.c (renamed from arch/arm/mach-at91rm9200/board-eb9200.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-ek.c (renamed from arch/arm/mach-at91rm9200/board-ek.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-kafa.c (renamed from arch/arm/mach-at91rm9200/board-kafa.c) | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-kb9202.c (renamed from arch/arm/mach-at91rm9200/board-kb9202.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-sam9260ek.c (renamed from arch/arm/mach-at91rm9200/board-sam9260ek.c) | 6 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-sam9261ek.c (renamed from arch/arm/mach-at91rm9200/board-sam9261ek.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/board-sam9263ek.c | 176 | ||||
-rw-r--r-- | arch/arm/mach-at91/clock.c (renamed from arch/arm/mach-at91rm9200/clock.c) | 64 | ||||
-rw-r--r-- | arch/arm/mach-at91/clock.h (renamed from arch/arm/mach-at91rm9200/clock.h) | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/generic.h (renamed from arch/arm/mach-at91rm9200/generic.h) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/gpio.c (renamed from arch/arm/mach-at91rm9200/gpio.c) | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/irq.c (renamed from arch/arm/mach-at91rm9200/irq.c) | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/leds.c (renamed from arch/arm/mach-at91rm9200/leds.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-at91/pm.c (renamed from arch/arm/mach-at91rm9200/pm.c) | 4 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/clock.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/core.c | 115 | ||||
-rw-r--r-- | arch/arm/mach-realview/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm/mach-realview/platsmp.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-realview/realview_eb.c | 38 | ||||
-rw-r--r-- | arch/arm/mach-s3c2400/Kconfig | 13 | ||||
-rw-r--r-- | arch/arm/mach-s3c2400/Makefile | 15 | ||||
-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/Kconfig | 338 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/Makefile | 103 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/bast-irq.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/bast.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/clock.c | 565 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/clock.h | 63 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/common-smdk.h | 15 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/cpu.h | 69 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/devs.h | 51 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/dma.c | 1546 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/dma.h | 45 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/gpio.c | 165 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/irq.c | 775 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/irq.h | 107 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-amlm5900.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-bast.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-h1940.c | 64 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-n30.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-otom.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-qt2410.c | 448 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-smdk2410.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/mach-vr1000.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/pm.c | 653 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/pm.h | 73 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2400.h | 31 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-clock.c | 276 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-dma.c | 161 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-gpio.c | 71 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-irq.c | 48 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-pm.c | 156 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410-sleep.S | 68 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2410.h | 31 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2412.h | 29 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2440.h | 17 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/s3c2442.h | 17 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/sleep.S | 151 | ||||
-rw-r--r-- | arch/arm/mach-s3c2410/usb-simtec.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c2412/Kconfig | 58 | ||||
-rw-r--r-- | arch/arm/mach-s3c2412/Makefile | 21 | ||||
-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/Kconfig | 71 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/Makefile | 23 | ||||
-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/Kconfig | 27 | ||||
-rw-r--r-- | arch/arm/mach-s3c2442/Makefile | 16 | ||||
-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/Kconfig | 29 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/Makefile | 20 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/clock.c | 1007 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/dma.c | 180 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/irq.c | 290 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/mach-smdk2443.c | 137 | ||||
-rw-r--r-- | arch/arm/mach-s3c2443/s3c2443.c | 97 | ||||
-rw-r--r-- | arch/arm/mm/Kconfig | 11 | ||||
-rw-r--r-- | arch/arm/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mm/cache-l2x0.c | 104 | ||||
-rw-r--r-- | arch/arm/mm/consistent.c | 17 | ||||
-rw-r--r-- | arch/arm/mm/context.c | 12 | ||||
-rw-r--r-- | arch/arm/mm/fault-armv.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 3 | ||||
-rw-r--r-- | arch/arm/mm/proc-v6.S | 22 | ||||
-rw-r--r-- | arch/arm/mm/proc-xsc3.S | 151 | ||||
-rw-r--r-- | arch/arm/mm/tlb-v6.S | 4 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/Kconfig | 99 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/Makefile | 30 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/clock.c | 449 | ||||
-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.c | 1499 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/gpio.c | 188 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/irq.c | 801 | ||||
-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.c | 659 | ||||
-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.S | 157 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/time.c (renamed from arch/arm/mach-s3c2410/time.c) | 6 |
156 files changed, 10851 insertions, 5596 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f7fa24b96eaa..195650935c78 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -304,7 +304,7 @@ config ARCH_SA1100 | |||
304 | Support for StrongARM 11x0 based boards. | 304 | Support for StrongARM 11x0 based boards. |
305 | 305 | ||
306 | config ARCH_S3C2410 | 306 | config ARCH_S3C2410 |
307 | bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442" | 307 | bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" |
308 | help | 308 | help |
309 | Samsung S3C2410X CPU based systems, such as the Simtec Electronics | 309 | Samsung S3C2410X CPU based systems, such as the Simtec Electronics |
310 | 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 |
@@ -364,7 +364,16 @@ source "arch/arm/mach-omap1/Kconfig" | |||
364 | 364 | ||
365 | source "arch/arm/mach-omap2/Kconfig" | 365 | source "arch/arm/mach-omap2/Kconfig" |
366 | 366 | ||
367 | source "arch/arm/plat-s3c24xx/Kconfig" | ||
368 | |||
369 | if ARCH_S3C2410 | ||
370 | source "arch/arm/mach-s3c2400/Kconfig" | ||
367 | source "arch/arm/mach-s3c2410/Kconfig" | 371 | source "arch/arm/mach-s3c2410/Kconfig" |
372 | source "arch/arm/mach-s3c2412/Kconfig" | ||
373 | source "arch/arm/mach-s3c2440/Kconfig" | ||
374 | source "arch/arm/mach-s3c2442/Kconfig" | ||
375 | source "arch/arm/mach-s3c2443/Kconfig" | ||
376 | endif | ||
368 | 377 | ||
369 | source "arch/arm/mach-lh7a40x/Kconfig" | 378 | source "arch/arm/mach-lh7a40x/Kconfig" |
370 | 379 | ||
@@ -378,7 +387,7 @@ source "arch/arm/mach-aaec2000/Kconfig" | |||
378 | 387 | ||
379 | source "arch/arm/mach-realview/Kconfig" | 388 | source "arch/arm/mach-realview/Kconfig" |
380 | 389 | ||
381 | source "arch/arm/mach-at91rm9200/Kconfig" | 390 | source "arch/arm/mach-at91/Kconfig" |
382 | 391 | ||
383 | source "arch/arm/mach-netx/Kconfig" | 392 | source "arch/arm/mach-netx/Kconfig" |
384 | 393 | ||
@@ -739,6 +748,20 @@ config XIP_PHYS_ADDR | |||
739 | 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 |
740 | own flash usage. | 749 | own flash usage. |
741 | 750 | ||
751 | config 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 | |||
742 | endmenu | 765 | endmenu |
743 | 766 | ||
744 | if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX ) | 767 | if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX ) |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 000f1100b553..2cd871c82c96 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -124,7 +124,7 @@ endif | |||
124 | machine-$(CONFIG_ARCH_H720X) := h720x | 124 | machine-$(CONFIG_ARCH_H720X) := h720x |
125 | machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 | 125 | machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 |
126 | machine-$(CONFIG_ARCH_REALVIEW) := realview | 126 | machine-$(CONFIG_ARCH_REALVIEW) := realview |
127 | machine-$(CONFIG_ARCH_AT91) := at91rm9200 | 127 | machine-$(CONFIG_ARCH_AT91) := at91 |
128 | machine-$(CONFIG_ARCH_EP93XX) := ep93xx | 128 | machine-$(CONFIG_ARCH_EP93XX) := ep93xx |
129 | machine-$(CONFIG_ARCH_PNX4008) := pnx4008 | 129 | machine-$(CONFIG_ARCH_PNX4008) := pnx4008 |
130 | machine-$(CONFIG_ARCH_NETX) := netx | 130 | machine-$(CONFIG_ARCH_NETX) := netx |
@@ -149,7 +149,7 @@ MACHINE := arch/arm/mach-$(machine-y)/ | |||
149 | else | 149 | else |
150 | MACHINE := | 150 | MACHINE := |
151 | endif | 151 | endif |
152 | 152 | ||
153 | export TEXT_OFFSET GZFLAGS MMUEXT | 153 | export 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. |
162 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ | 162 | core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ |
163 | core-y += $(MACHINE) | 163 | core-y += $(MACHINE) |
164 | core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2400/ | ||
165 | core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2412/ | ||
166 | core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2440/ | ||
167 | core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2442/ | ||
168 | core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2443/ | ||
164 | core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ | 169 | core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ |
165 | core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) | 170 | core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) |
166 | core-$(CONFIG_VFP) += arch/arm/vfp/ | 171 | core-$(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. |
169 | core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/ | 174 | core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/ |
170 | core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/ | 175 | core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/ |
176 | core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/ | ||
171 | 177 | ||
172 | drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ | 178 | drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ |
173 | drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ | 179 | drivers-$(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 @@ | |||
1 | Image | ||
2 | zImage | ||
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 | ||
68 | struct dmabounce_device_info { | 67 | struct 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 | ||
84 | static LIST_HEAD(dmabounce_devs); | ||
85 | |||
86 | #ifdef STATS | 82 | #ifdef STATS |
87 | static void print_alloc_stats(struct dmabounce_device_info *device_info) | 83 | static 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 */ | ||
100 | static inline struct dmabounce_device_info * | ||
101 | find_dmabounce_dev(struct device *dev) | ||
102 | { | ||
103 | struct dmabounce_device_info *d; | ||
104 | 96 | ||
105 | list_for_each_entry(d, &dmabounce_devs, node) | 97 | static 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 | ||
222 | static 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 | |||
230 | static inline dma_addr_t | 207 | static inline dma_addr_t |
231 | map_single(struct device *dev, void *ptr, size_t size, | 208 | map_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 | |||
292 | unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 273 | unmap_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 | |||
343 | sync_single(struct device *dev, dma_addr_t dma_addr, size_t size, | 324 | sync_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, | |||
623 | void | 608 | void |
624 | dmabounce_unregister_dev(struct device *dev) | 609 | dmabounce_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 | ||
34 | static void __iomem *gic_dist_base; | ||
35 | static void __iomem *gic_cpu_base; | ||
36 | static DEFINE_SPINLOCK(irq_controller_lock); | 36 | static DEFINE_SPINLOCK(irq_controller_lock); |
37 | 37 | ||
38 | struct 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 | |||
48 | static struct gic_chip_data gic_data[MAX_GIC_NR]; | ||
49 | |||
50 | static 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 | |||
56 | static 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 | |||
62 | static 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 |
82 | static void gic_set_cpu(unsigned int irq, cpumask_t mask_val) | 112 | static 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 | ||
128 | static 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 | |||
98 | static struct irq_chip gic_chip = { | 159 | static 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 | ||
108 | void __init gic_dist_init(void __iomem *base) | 169 | void __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 | |||
178 | void __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 | ||
170 | void __cpuinit gic_cpu_init(void __iomem *base) | 246 | void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) |
171 | { | 247 | { |
172 | gic_cpu_base = base; | 248 | if (gic_nr >= MAX_GIC_NR) |
249 | BUG(); | ||
250 | |||
251 | gic_data[gic_nr].cpu_base = base; | ||
252 | |||
173 | writel(0xf0, base + GIC_CPU_PRIMASK); | 253 | writel(0xf0, base + GIC_CPU_PRIMASK); |
174 | writel(1, base + GIC_CPU_CTRL); | 254 | writel(1, base + GIC_CPU_CTRL); |
175 | } | 255 | } |
@@ -179,6 +259,7 @@ void gic_raise_softirq(cpumask_t cpumask, unsigned int irq) | |||
179 | { | 259 | { |
180 | unsigned long map = *cpus_addr(cpumask); | 260 | unsigned long map = *cpus_addr(cpumask); |
181 | 261 | ||
182 | writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT); | 262 | /* this always happens on GIC0 */ |
263 | writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); | ||
183 | } | 264 | } |
184 | #endif | 265 | #endif |
diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig new file mode 100644 index 000000000000..c72ab82873d5 --- /dev/null +++ b/arch/arm/configs/at91sam9263ek_defconfig | |||
@@ -0,0 +1,1184 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.20-rc1 | ||
4 | # Mon Jan 8 16:06:54 2007 | ||
5 | # | ||
6 | CONFIG_ARM=y | ||
7 | # CONFIG_GENERIC_TIME is not set | ||
8 | CONFIG_MMU=y | ||
9 | CONFIG_GENERIC_HARDIRQS=y | ||
10 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | ||
11 | CONFIG_HARDIRQS_SW_RESEND=y | ||
12 | CONFIG_GENERIC_IRQ_PROBE=y | ||
13 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
14 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set | ||
15 | # CONFIG_ARCH_HAS_ILOG2_U64 is not set | ||
16 | CONFIG_GENERIC_HWEIGHT=y | ||
17 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
18 | CONFIG_VECTORS_BASE=0xffff0000 | ||
19 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | ||
20 | |||
21 | # | ||
22 | # Code maturity level options | ||
23 | # | ||
24 | CONFIG_EXPERIMENTAL=y | ||
25 | CONFIG_BROKEN_ON_SMP=y | ||
26 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
27 | |||
28 | # | ||
29 | # General setup | ||
30 | # | ||
31 | CONFIG_LOCALVERSION="" | ||
32 | # CONFIG_LOCALVERSION_AUTO is not set | ||
33 | # CONFIG_SWAP is not set | ||
34 | CONFIG_SYSVIPC=y | ||
35 | # CONFIG_IPC_NS is not set | ||
36 | # CONFIG_POSIX_MQUEUE is not set | ||
37 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
38 | # CONFIG_TASKSTATS is not set | ||
39 | # CONFIG_UTS_NS is not set | ||
40 | # CONFIG_AUDIT is not set | ||
41 | # CONFIG_IKCONFIG is not set | ||
42 | CONFIG_SYSFS_DEPRECATED=y | ||
43 | # CONFIG_RELAY is not set | ||
44 | CONFIG_INITRAMFS_SOURCE="" | ||
45 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
46 | CONFIG_SYSCTL=y | ||
47 | # CONFIG_EMBEDDED is not set | ||
48 | CONFIG_UID16=y | ||
49 | CONFIG_SYSCTL_SYSCALL=y | ||
50 | CONFIG_KALLSYMS=y | ||
51 | # CONFIG_KALLSYMS_ALL is not set | ||
52 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
53 | CONFIG_HOTPLUG=y | ||
54 | CONFIG_PRINTK=y | ||
55 | CONFIG_BUG=y | ||
56 | CONFIG_ELF_CORE=y | ||
57 | CONFIG_BASE_FULL=y | ||
58 | CONFIG_FUTEX=y | ||
59 | CONFIG_EPOLL=y | ||
60 | CONFIG_SHMEM=y | ||
61 | CONFIG_SLAB=y | ||
62 | CONFIG_VM_EVENT_COUNTERS=y | ||
63 | CONFIG_RT_MUTEXES=y | ||
64 | # CONFIG_TINY_SHMEM is not set | ||
65 | CONFIG_BASE_SMALL=0 | ||
66 | # CONFIG_SLOB is not set | ||
67 | |||
68 | # | ||
69 | # Loadable module support | ||
70 | # | ||
71 | CONFIG_MODULES=y | ||
72 | CONFIG_MODULE_UNLOAD=y | ||
73 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
74 | # CONFIG_MODVERSIONS is not set | ||
75 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
76 | CONFIG_KMOD=y | ||
77 | |||
78 | # | ||
79 | # Block layer | ||
80 | # | ||
81 | CONFIG_BLOCK=y | ||
82 | # CONFIG_LBD is not set | ||
83 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
84 | # CONFIG_LSF is not set | ||
85 | |||
86 | # | ||
87 | # IO Schedulers | ||
88 | # | ||
89 | CONFIG_IOSCHED_NOOP=y | ||
90 | CONFIG_IOSCHED_AS=y | ||
91 | # CONFIG_IOSCHED_DEADLINE is not set | ||
92 | # CONFIG_IOSCHED_CFQ is not set | ||
93 | CONFIG_DEFAULT_AS=y | ||
94 | # CONFIG_DEFAULT_DEADLINE is not set | ||
95 | # CONFIG_DEFAULT_CFQ is not set | ||
96 | # CONFIG_DEFAULT_NOOP is not set | ||
97 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
98 | |||
99 | # | ||
100 | # System Type | ||
101 | # | ||
102 | # CONFIG_ARCH_AAEC2000 is not set | ||
103 | # CONFIG_ARCH_INTEGRATOR is not set | ||
104 | # CONFIG_ARCH_REALVIEW is not set | ||
105 | # CONFIG_ARCH_VERSATILE is not set | ||
106 | CONFIG_ARCH_AT91=y | ||
107 | # CONFIG_ARCH_CLPS7500 is not set | ||
108 | # CONFIG_ARCH_CLPS711X is not set | ||
109 | # CONFIG_ARCH_CO285 is not set | ||
110 | # CONFIG_ARCH_EBSA110 is not set | ||
111 | # CONFIG_ARCH_EP93XX is not set | ||
112 | # CONFIG_ARCH_FOOTBRIDGE is not set | ||
113 | # CONFIG_ARCH_NETX is not set | ||
114 | # CONFIG_ARCH_H720X is not set | ||
115 | # CONFIG_ARCH_IMX is not set | ||
116 | # CONFIG_ARCH_IOP32X is not set | ||
117 | # CONFIG_ARCH_IOP33X is not set | ||
118 | # CONFIG_ARCH_IOP13XX is not set | ||
119 | # CONFIG_ARCH_IXP4XX is not set | ||
120 | # CONFIG_ARCH_IXP2000 is not set | ||
121 | # CONFIG_ARCH_IXP23XX is not set | ||
122 | # CONFIG_ARCH_L7200 is not set | ||
123 | # CONFIG_ARCH_PNX4008 is not set | ||
124 | # CONFIG_ARCH_PXA is not set | ||
125 | # CONFIG_ARCH_RPC is not set | ||
126 | # CONFIG_ARCH_SA1100 is not set | ||
127 | # CONFIG_ARCH_S3C2410 is not set | ||
128 | # CONFIG_ARCH_SHARK is not set | ||
129 | # CONFIG_ARCH_LH7A40X is not set | ||
130 | # CONFIG_ARCH_OMAP is not set | ||
131 | |||
132 | # | ||
133 | # Atmel AT91 System-on-Chip | ||
134 | # | ||
135 | # CONFIG_ARCH_AT91RM9200 is not set | ||
136 | # CONFIG_ARCH_AT91SAM9260 is not set | ||
137 | # CONFIG_ARCH_AT91SAM9261 is not set | ||
138 | CONFIG_ARCH_AT91SAM9263=y | ||
139 | |||
140 | # | ||
141 | # AT91SAM9263 Board Type | ||
142 | # | ||
143 | CONFIG_MACH_AT91SAM9263EK=y | ||
144 | |||
145 | # | ||
146 | # AT91 Board Options | ||
147 | # | ||
148 | CONFIG_MTD_AT91_DATAFLASH_CARD=y | ||
149 | # CONFIG_MTD_NAND_AT91_BUSWIDTH_16 is not set | ||
150 | |||
151 | # | ||
152 | # AT91 Feature Selections | ||
153 | # | ||
154 | # CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set | ||
155 | |||
156 | # | ||
157 | # Processor Type | ||
158 | # | ||
159 | CONFIG_CPU_32=y | ||
160 | CONFIG_CPU_ARM926T=y | ||
161 | CONFIG_CPU_32v5=y | ||
162 | CONFIG_CPU_ABRT_EV5TJ=y | ||
163 | CONFIG_CPU_CACHE_VIVT=y | ||
164 | CONFIG_CPU_COPY_V4WB=y | ||
165 | CONFIG_CPU_TLB_V4WBI=y | ||
166 | CONFIG_CPU_CP15=y | ||
167 | CONFIG_CPU_CP15_MMU=y | ||
168 | |||
169 | # | ||
170 | # Processor Features | ||
171 | # | ||
172 | # CONFIG_ARM_THUMB is not set | ||
173 | # CONFIG_CPU_ICACHE_DISABLE is not set | ||
174 | # CONFIG_CPU_DCACHE_DISABLE is not set | ||
175 | # CONFIG_CPU_DCACHE_WRITETHROUGH is not set | ||
176 | # CONFIG_CPU_CACHE_ROUND_ROBIN is not set | ||
177 | |||
178 | # | ||
179 | # Bus support | ||
180 | # | ||
181 | |||
182 | # | ||
183 | # PCCARD (PCMCIA/CardBus) support | ||
184 | # | ||
185 | # CONFIG_PCCARD is not set | ||
186 | |||
187 | # | ||
188 | # Kernel Features | ||
189 | # | ||
190 | # CONFIG_PREEMPT is not set | ||
191 | # CONFIG_NO_IDLE_HZ is not set | ||
192 | CONFIG_HZ=100 | ||
193 | # CONFIG_AEABI is not set | ||
194 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | ||
195 | CONFIG_SELECT_MEMORY_MODEL=y | ||
196 | CONFIG_FLATMEM_MANUAL=y | ||
197 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
198 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
199 | CONFIG_FLATMEM=y | ||
200 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
201 | # CONFIG_SPARSEMEM_STATIC is not set | ||
202 | CONFIG_SPLIT_PTLOCK_CPUS=4096 | ||
203 | # CONFIG_RESOURCES_64BIT is not set | ||
204 | # CONFIG_LEDS is not set | ||
205 | CONFIG_ALIGNMENT_TRAP=y | ||
206 | |||
207 | # | ||
208 | # Boot options | ||
209 | # | ||
210 | CONFIG_ZBOOT_ROM_TEXT=0x0 | ||
211 | CONFIG_ZBOOT_ROM_BSS=0x0 | ||
212 | CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" | ||
213 | # CONFIG_XIP_KERNEL is not set | ||
214 | |||
215 | # | ||
216 | # Floating point emulation | ||
217 | # | ||
218 | |||
219 | # | ||
220 | # At least one emulation must be selected | ||
221 | # | ||
222 | CONFIG_FPE_NWFPE=y | ||
223 | # CONFIG_FPE_NWFPE_XP is not set | ||
224 | # CONFIG_FPE_FASTFPE is not set | ||
225 | # CONFIG_VFP is not set | ||
226 | |||
227 | # | ||
228 | # Userspace binary formats | ||
229 | # | ||
230 | CONFIG_BINFMT_ELF=y | ||
231 | # CONFIG_BINFMT_AOUT is not set | ||
232 | # CONFIG_BINFMT_MISC is not set | ||
233 | # CONFIG_ARTHUR is not set | ||
234 | |||
235 | # | ||
236 | # Power management options | ||
237 | # | ||
238 | # CONFIG_PM is not set | ||
239 | # CONFIG_APM is not set | ||
240 | |||
241 | # | ||
242 | # Networking | ||
243 | # | ||
244 | CONFIG_NET=y | ||
245 | |||
246 | # | ||
247 | # Networking options | ||
248 | # | ||
249 | # CONFIG_NETDEBUG is not set | ||
250 | CONFIG_PACKET=y | ||
251 | # CONFIG_PACKET_MMAP is not set | ||
252 | CONFIG_UNIX=y | ||
253 | # CONFIG_NET_KEY is not set | ||
254 | CONFIG_INET=y | ||
255 | # CONFIG_IP_MULTICAST is not set | ||
256 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
257 | CONFIG_IP_FIB_HASH=y | ||
258 | CONFIG_IP_PNP=y | ||
259 | # CONFIG_IP_PNP_DHCP is not set | ||
260 | CONFIG_IP_PNP_BOOTP=y | ||
261 | CONFIG_IP_PNP_RARP=y | ||
262 | # CONFIG_NET_IPIP is not set | ||
263 | # CONFIG_NET_IPGRE is not set | ||
264 | # CONFIG_ARPD is not set | ||
265 | # CONFIG_SYN_COOKIES is not set | ||
266 | # CONFIG_INET_AH is not set | ||
267 | # CONFIG_INET_ESP is not set | ||
268 | # CONFIG_INET_IPCOMP is not set | ||
269 | # CONFIG_INET_XFRM_TUNNEL is not set | ||
270 | # CONFIG_INET_TUNNEL is not set | ||
271 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set | ||
272 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set | ||
273 | # CONFIG_INET_XFRM_MODE_BEET is not set | ||
274 | # CONFIG_INET_DIAG is not set | ||
275 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
276 | CONFIG_TCP_CONG_CUBIC=y | ||
277 | CONFIG_DEFAULT_TCP_CONG="cubic" | ||
278 | # CONFIG_TCP_MD5SIG is not set | ||
279 | # CONFIG_IPV6 is not set | ||
280 | # CONFIG_INET6_XFRM_TUNNEL is not set | ||
281 | # CONFIG_INET6_TUNNEL is not set | ||
282 | # CONFIG_NETWORK_SECMARK is not set | ||
283 | # CONFIG_NETFILTER is not set | ||
284 | |||
285 | # | ||
286 | # DCCP Configuration (EXPERIMENTAL) | ||
287 | # | ||
288 | # CONFIG_IP_DCCP is not set | ||
289 | |||
290 | # | ||
291 | # SCTP Configuration (EXPERIMENTAL) | ||
292 | # | ||
293 | # CONFIG_IP_SCTP is not set | ||
294 | |||
295 | # | ||
296 | # TIPC Configuration (EXPERIMENTAL) | ||
297 | # | ||
298 | # CONFIG_TIPC is not set | ||
299 | # CONFIG_ATM is not set | ||
300 | # CONFIG_BRIDGE is not set | ||
301 | # CONFIG_VLAN_8021Q is not set | ||
302 | # CONFIG_DECNET is not set | ||
303 | # CONFIG_LLC2 is not set | ||
304 | # CONFIG_IPX is not set | ||
305 | # CONFIG_ATALK is not set | ||
306 | # CONFIG_X25 is not set | ||
307 | # CONFIG_LAPB is not set | ||
308 | # CONFIG_ECONET is not set | ||
309 | # CONFIG_WAN_ROUTER is not set | ||
310 | |||
311 | # | ||
312 | # QoS and/or fair queueing | ||
313 | # | ||
314 | # CONFIG_NET_SCHED is not set | ||
315 | |||
316 | # | ||
317 | # Network testing | ||
318 | # | ||
319 | # CONFIG_NET_PKTGEN is not set | ||
320 | # CONFIG_HAMRADIO is not set | ||
321 | # CONFIG_IRDA is not set | ||
322 | # CONFIG_BT is not set | ||
323 | # CONFIG_IEEE80211 is not set | ||
324 | |||
325 | # | ||
326 | # Device Drivers | ||
327 | # | ||
328 | |||
329 | # | ||
330 | # Generic Driver Options | ||
331 | # | ||
332 | CONFIG_STANDALONE=y | ||
333 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
334 | # CONFIG_FW_LOADER is not set | ||
335 | # CONFIG_DEBUG_DRIVER is not set | ||
336 | # CONFIG_SYS_HYPERVISOR is not set | ||
337 | |||
338 | # | ||
339 | # Connector - unified userspace <-> kernelspace linker | ||
340 | # | ||
341 | # CONFIG_CONNECTOR is not set | ||
342 | |||
343 | # | ||
344 | # Memory Technology Devices (MTD) | ||
345 | # | ||
346 | CONFIG_MTD=y | ||
347 | # CONFIG_MTD_DEBUG is not set | ||
348 | # CONFIG_MTD_CONCAT is not set | ||
349 | CONFIG_MTD_PARTITIONS=y | ||
350 | # CONFIG_MTD_REDBOOT_PARTS is not set | ||
351 | CONFIG_MTD_CMDLINE_PARTS=y | ||
352 | # CONFIG_MTD_AFS_PARTS is not set | ||
353 | |||
354 | # | ||
355 | # User Modules And Translation Layers | ||
356 | # | ||
357 | CONFIG_MTD_CHAR=y | ||
358 | CONFIG_MTD_BLKDEVS=y | ||
359 | CONFIG_MTD_BLOCK=y | ||
360 | # CONFIG_FTL is not set | ||
361 | # CONFIG_NFTL is not set | ||
362 | # CONFIG_INFTL is not set | ||
363 | # CONFIG_RFD_FTL is not set | ||
364 | # CONFIG_SSFDC is not set | ||
365 | |||
366 | # | ||
367 | # RAM/ROM/Flash chip drivers | ||
368 | # | ||
369 | # CONFIG_MTD_CFI is not set | ||
370 | # CONFIG_MTD_JEDECPROBE is not set | ||
371 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
372 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
373 | CONFIG_MTD_MAP_BANK_WIDTH_4=y | ||
374 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
375 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
376 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
377 | CONFIG_MTD_CFI_I1=y | ||
378 | CONFIG_MTD_CFI_I2=y | ||
379 | # CONFIG_MTD_CFI_I4 is not set | ||
380 | # CONFIG_MTD_CFI_I8 is not set | ||
381 | # CONFIG_MTD_RAM is not set | ||
382 | # CONFIG_MTD_ROM is not set | ||
383 | # CONFIG_MTD_ABSENT is not set | ||
384 | # CONFIG_MTD_OBSOLETE_CHIPS is not set | ||
385 | |||
386 | # | ||
387 | # Mapping drivers for chip access | ||
388 | # | ||
389 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | ||
390 | # CONFIG_MTD_PLATRAM is not set | ||
391 | |||
392 | # | ||
393 | # Self-contained MTD device drivers | ||
394 | # | ||
395 | CONFIG_MTD_DATAFLASH=y | ||
396 | # CONFIG_MTD_M25P80 is not set | ||
397 | # CONFIG_MTD_SLRAM is not set | ||
398 | # CONFIG_MTD_PHRAM is not set | ||
399 | # CONFIG_MTD_MTDRAM is not set | ||
400 | # CONFIG_MTD_BLOCK2MTD is not set | ||
401 | |||
402 | # | ||
403 | # Disk-On-Chip Device Drivers | ||
404 | # | ||
405 | # CONFIG_MTD_DOC2000 is not set | ||
406 | # CONFIG_MTD_DOC2001 is not set | ||
407 | # CONFIG_MTD_DOC2001PLUS is not set | ||
408 | |||
409 | # | ||
410 | # NAND Flash Device Drivers | ||
411 | # | ||
412 | CONFIG_MTD_NAND=y | ||
413 | # CONFIG_MTD_NAND_VERIFY_WRITE is not set | ||
414 | # CONFIG_MTD_NAND_ECC_SMC is not set | ||
415 | CONFIG_MTD_NAND_IDS=y | ||
416 | # CONFIG_MTD_NAND_DISKONCHIP is not set | ||
417 | CONFIG_MTD_NAND_AT91=y | ||
418 | # CONFIG_MTD_NAND_NANDSIM is not set | ||
419 | |||
420 | # | ||
421 | # OneNAND Flash Device Drivers | ||
422 | # | ||
423 | # CONFIG_MTD_ONENAND is not set | ||
424 | |||
425 | # | ||
426 | # Parallel port support | ||
427 | # | ||
428 | # CONFIG_PARPORT is not set | ||
429 | |||
430 | # | ||
431 | # Plug and Play support | ||
432 | # | ||
433 | |||
434 | # | ||
435 | # Block devices | ||
436 | # | ||
437 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
438 | CONFIG_BLK_DEV_LOOP=y | ||
439 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
440 | # CONFIG_BLK_DEV_NBD is not set | ||
441 | # CONFIG_BLK_DEV_UB is not set | ||
442 | CONFIG_BLK_DEV_RAM=y | ||
443 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
444 | CONFIG_BLK_DEV_RAM_SIZE=8192 | ||
445 | CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 | ||
446 | CONFIG_BLK_DEV_INITRD=y | ||
447 | # CONFIG_CDROM_PKTCDVD is not set | ||
448 | # CONFIG_ATA_OVER_ETH is not set | ||
449 | |||
450 | # | ||
451 | # SCSI device support | ||
452 | # | ||
453 | # CONFIG_RAID_ATTRS is not set | ||
454 | CONFIG_SCSI=y | ||
455 | # CONFIG_SCSI_TGT is not set | ||
456 | # CONFIG_SCSI_NETLINK is not set | ||
457 | CONFIG_SCSI_PROC_FS=y | ||
458 | |||
459 | # | ||
460 | # SCSI support type (disk, tape, CD-ROM) | ||
461 | # | ||
462 | CONFIG_BLK_DEV_SD=y | ||
463 | # CONFIG_CHR_DEV_ST is not set | ||
464 | # CONFIG_CHR_DEV_OSST is not set | ||
465 | # CONFIG_BLK_DEV_SR is not set | ||
466 | # CONFIG_CHR_DEV_SG is not set | ||
467 | # CONFIG_CHR_DEV_SCH is not set | ||
468 | |||
469 | # | ||
470 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | ||
471 | # | ||
472 | CONFIG_SCSI_MULTI_LUN=y | ||
473 | # CONFIG_SCSI_CONSTANTS is not set | ||
474 | # CONFIG_SCSI_LOGGING is not set | ||
475 | # CONFIG_SCSI_SCAN_ASYNC is not set | ||
476 | |||
477 | # | ||
478 | # SCSI Transports | ||
479 | # | ||
480 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
481 | # CONFIG_SCSI_FC_ATTRS is not set | ||
482 | # CONFIG_SCSI_ISCSI_ATTRS is not set | ||
483 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
484 | # CONFIG_SCSI_SAS_LIBSAS is not set | ||
485 | |||
486 | # | ||
487 | # SCSI low-level drivers | ||
488 | # | ||
489 | # CONFIG_ISCSI_TCP is not set | ||
490 | # CONFIG_SCSI_DEBUG is not set | ||
491 | |||
492 | # | ||
493 | # Serial ATA (prod) and Parallel ATA (experimental) drivers | ||
494 | # | ||
495 | # CONFIG_ATA is not set | ||
496 | |||
497 | # | ||
498 | # Multi-device support (RAID and LVM) | ||
499 | # | ||
500 | # CONFIG_MD is not set | ||
501 | |||
502 | # | ||
503 | # Fusion MPT device support | ||
504 | # | ||
505 | # CONFIG_FUSION is not set | ||
506 | |||
507 | # | ||
508 | # IEEE 1394 (FireWire) support | ||
509 | # | ||
510 | |||
511 | # | ||
512 | # I2O device support | ||
513 | # | ||
514 | |||
515 | # | ||
516 | # Network device support | ||
517 | # | ||
518 | CONFIG_NETDEVICES=y | ||
519 | # CONFIG_DUMMY is not set | ||
520 | # CONFIG_BONDING is not set | ||
521 | # CONFIG_EQUALIZER is not set | ||
522 | # CONFIG_TUN is not set | ||
523 | |||
524 | # | ||
525 | # PHY device support | ||
526 | # | ||
527 | # CONFIG_PHYLIB is not set | ||
528 | |||
529 | # | ||
530 | # Ethernet (10 or 100Mbit) | ||
531 | # | ||
532 | CONFIG_NET_ETHERNET=y | ||
533 | CONFIG_MII=y | ||
534 | # CONFIG_SMC91X is not set | ||
535 | # CONFIG_DM9000 is not set | ||
536 | |||
537 | # | ||
538 | # Ethernet (1000 Mbit) | ||
539 | # | ||
540 | |||
541 | # | ||
542 | # Ethernet (10000 Mbit) | ||
543 | # | ||
544 | |||
545 | # | ||
546 | # Token Ring devices | ||
547 | # | ||
548 | |||
549 | # | ||
550 | # Wireless LAN (non-hamradio) | ||
551 | # | ||
552 | # CONFIG_NET_RADIO is not set | ||
553 | |||
554 | # | ||
555 | # Wan interfaces | ||
556 | # | ||
557 | # CONFIG_WAN is not set | ||
558 | # CONFIG_PPP is not set | ||
559 | # CONFIG_SLIP is not set | ||
560 | # CONFIG_SHAPER is not set | ||
561 | # CONFIG_NETCONSOLE is not set | ||
562 | # CONFIG_NETPOLL is not set | ||
563 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
564 | |||
565 | # | ||
566 | # ISDN subsystem | ||
567 | # | ||
568 | # CONFIG_ISDN is not set | ||
569 | |||
570 | # | ||
571 | # Input device support | ||
572 | # | ||
573 | CONFIG_INPUT=y | ||
574 | # CONFIG_INPUT_FF_MEMLESS is not set | ||
575 | |||
576 | # | ||
577 | # Userland interfaces | ||
578 | # | ||
579 | CONFIG_INPUT_MOUSEDEV=y | ||
580 | # CONFIG_INPUT_MOUSEDEV_PSAUX is not set | ||
581 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 | ||
582 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | ||
583 | # CONFIG_INPUT_JOYDEV is not set | ||
584 | CONFIG_INPUT_TSDEV=y | ||
585 | CONFIG_INPUT_TSDEV_SCREEN_X=240 | ||
586 | CONFIG_INPUT_TSDEV_SCREEN_Y=320 | ||
587 | CONFIG_INPUT_EVDEV=y | ||
588 | # CONFIG_INPUT_EVBUG is not set | ||
589 | |||
590 | # | ||
591 | # Input Device Drivers | ||
592 | # | ||
593 | # CONFIG_INPUT_KEYBOARD is not set | ||
594 | # CONFIG_INPUT_MOUSE is not set | ||
595 | # CONFIG_INPUT_JOYSTICK is not set | ||
596 | CONFIG_INPUT_TOUCHSCREEN=y | ||
597 | CONFIG_TOUCHSCREEN_ADS7846=y | ||
598 | # CONFIG_TOUCHSCREEN_GUNZE is not set | ||
599 | # CONFIG_TOUCHSCREEN_ELO is not set | ||
600 | # CONFIG_TOUCHSCREEN_MTOUCH is not set | ||
601 | # CONFIG_TOUCHSCREEN_MK712 is not set | ||
602 | # CONFIG_TOUCHSCREEN_PENMOUNT is not set | ||
603 | # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set | ||
604 | # CONFIG_TOUCHSCREEN_TOUCHWIN is not set | ||
605 | # CONFIG_TOUCHSCREEN_UCB1400 is not set | ||
606 | # CONFIG_INPUT_MISC is not set | ||
607 | |||
608 | # | ||
609 | # Hardware I/O ports | ||
610 | # | ||
611 | # CONFIG_SERIO is not set | ||
612 | # CONFIG_GAMEPORT is not set | ||
613 | |||
614 | # | ||
615 | # Character devices | ||
616 | # | ||
617 | CONFIG_VT=y | ||
618 | CONFIG_VT_CONSOLE=y | ||
619 | CONFIG_HW_CONSOLE=y | ||
620 | # CONFIG_VT_HW_CONSOLE_BINDING is not set | ||
621 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
622 | |||
623 | # | ||
624 | # Serial drivers | ||
625 | # | ||
626 | # CONFIG_SERIAL_8250 is not set | ||
627 | |||
628 | # | ||
629 | # Non-8250 serial port support | ||
630 | # | ||
631 | CONFIG_SERIAL_ATMEL=y | ||
632 | CONFIG_SERIAL_ATMEL_CONSOLE=y | ||
633 | # CONFIG_SERIAL_ATMEL_TTYAT is not set | ||
634 | CONFIG_SERIAL_CORE=y | ||
635 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
636 | CONFIG_UNIX98_PTYS=y | ||
637 | CONFIG_LEGACY_PTYS=y | ||
638 | CONFIG_LEGACY_PTY_COUNT=256 | ||
639 | |||
640 | # | ||
641 | # IPMI | ||
642 | # | ||
643 | # CONFIG_IPMI_HANDLER is not set | ||
644 | |||
645 | # | ||
646 | # Watchdog Cards | ||
647 | # | ||
648 | CONFIG_WATCHDOG=y | ||
649 | CONFIG_WATCHDOG_NOWAYOUT=y | ||
650 | |||
651 | # | ||
652 | # Watchdog Device Drivers | ||
653 | # | ||
654 | # CONFIG_SOFT_WATCHDOG is not set | ||
655 | |||
656 | # | ||
657 | # USB-based Watchdog Cards | ||
658 | # | ||
659 | # CONFIG_USBPCWATCHDOG is not set | ||
660 | CONFIG_HW_RANDOM=y | ||
661 | # CONFIG_NVRAM is not set | ||
662 | # CONFIG_DTLK is not set | ||
663 | # CONFIG_R3964 is not set | ||
664 | # CONFIG_RAW_DRIVER is not set | ||
665 | |||
666 | # | ||
667 | # TPM devices | ||
668 | # | ||
669 | # CONFIG_TCG_TPM is not set | ||
670 | |||
671 | # | ||
672 | # I2C support | ||
673 | # | ||
674 | CONFIG_I2C=y | ||
675 | CONFIG_I2C_CHARDEV=y | ||
676 | |||
677 | # | ||
678 | # I2C Algorithms | ||
679 | # | ||
680 | # CONFIG_I2C_ALGOBIT is not set | ||
681 | # CONFIG_I2C_ALGOPCF is not set | ||
682 | # CONFIG_I2C_ALGOPCA is not set | ||
683 | |||
684 | # | ||
685 | # I2C Hardware Bus support | ||
686 | # | ||
687 | CONFIG_I2C_AT91=y | ||
688 | # CONFIG_I2C_OCORES is not set | ||
689 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
690 | # CONFIG_I2C_STUB is not set | ||
691 | # CONFIG_I2C_PCA is not set | ||
692 | # CONFIG_I2C_PCA_ISA is not set | ||
693 | |||
694 | # | ||
695 | # Miscellaneous I2C Chip support | ||
696 | # | ||
697 | # CONFIG_SENSORS_DS1337 is not set | ||
698 | # CONFIG_SENSORS_DS1374 is not set | ||
699 | # CONFIG_SENSORS_EEPROM is not set | ||
700 | # CONFIG_SENSORS_PCF8574 is not set | ||
701 | # CONFIG_SENSORS_PCA9539 is not set | ||
702 | # CONFIG_SENSORS_PCF8591 is not set | ||
703 | # CONFIG_SENSORS_MAX6875 is not set | ||
704 | # CONFIG_I2C_DEBUG_CORE is not set | ||
705 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
706 | # CONFIG_I2C_DEBUG_BUS is not set | ||
707 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
708 | |||
709 | # | ||
710 | # SPI support | ||
711 | # | ||
712 | CONFIG_SPI=y | ||
713 | # CONFIG_SPI_DEBUG is not set | ||
714 | CONFIG_SPI_MASTER=y | ||
715 | |||
716 | # | ||
717 | # SPI Master Controller Drivers | ||
718 | # | ||
719 | CONFIG_SPI_ATMEL=y | ||
720 | # CONFIG_SPI_BITBANG is not set | ||
721 | |||
722 | # | ||
723 | # SPI Protocol Masters | ||
724 | # | ||
725 | |||
726 | # | ||
727 | # Dallas's 1-wire bus | ||
728 | # | ||
729 | # CONFIG_W1 is not set | ||
730 | |||
731 | # | ||
732 | # Hardware Monitoring support | ||
733 | # | ||
734 | # CONFIG_HWMON is not set | ||
735 | # CONFIG_HWMON_VID is not set | ||
736 | |||
737 | # | ||
738 | # Misc devices | ||
739 | # | ||
740 | # CONFIG_TIFM_CORE is not set | ||
741 | |||
742 | # | ||
743 | # LED devices | ||
744 | # | ||
745 | # CONFIG_NEW_LEDS is not set | ||
746 | |||
747 | # | ||
748 | # LED drivers | ||
749 | # | ||
750 | |||
751 | # | ||
752 | # LED Triggers | ||
753 | # | ||
754 | |||
755 | # | ||
756 | # Multimedia devices | ||
757 | # | ||
758 | # CONFIG_VIDEO_DEV is not set | ||
759 | |||
760 | # | ||
761 | # Digital Video Broadcasting Devices | ||
762 | # | ||
763 | # CONFIG_DVB is not set | ||
764 | # CONFIG_USB_DABUSB is not set | ||
765 | |||
766 | # | ||
767 | # Graphics support | ||
768 | # | ||
769 | # CONFIG_FIRMWARE_EDID is not set | ||
770 | CONFIG_FB=y | ||
771 | # CONFIG_FB_CFB_FILLRECT is not set | ||
772 | # CONFIG_FB_CFB_COPYAREA is not set | ||
773 | # CONFIG_FB_CFB_IMAGEBLIT is not set | ||
774 | # CONFIG_FB_MACMODES is not set | ||
775 | # CONFIG_FB_BACKLIGHT is not set | ||
776 | # CONFIG_FB_MODE_HELPERS is not set | ||
777 | # CONFIG_FB_TILEBLITTING is not set | ||
778 | # CONFIG_FB_S1D13XXX is not set | ||
779 | # CONFIG_FB_VIRTUAL is not set | ||
780 | |||
781 | # | ||
782 | # Console display driver support | ||
783 | # | ||
784 | # CONFIG_VGA_CONSOLE is not set | ||
785 | CONFIG_DUMMY_CONSOLE=y | ||
786 | # CONFIG_FRAMEBUFFER_CONSOLE is not set | ||
787 | |||
788 | # | ||
789 | # Logo configuration | ||
790 | # | ||
791 | # CONFIG_LOGO is not set | ||
792 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | ||
793 | |||
794 | # | ||
795 | # Sound | ||
796 | # | ||
797 | # CONFIG_SOUND is not set | ||
798 | |||
799 | # | ||
800 | # HID Devices | ||
801 | # | ||
802 | CONFIG_HID=y | ||
803 | |||
804 | # | ||
805 | # USB support | ||
806 | # | ||
807 | CONFIG_USB_ARCH_HAS_HCD=y | ||
808 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
809 | # CONFIG_USB_ARCH_HAS_EHCI is not set | ||
810 | CONFIG_USB=y | ||
811 | # CONFIG_USB_DEBUG is not set | ||
812 | |||
813 | # | ||
814 | # Miscellaneous USB options | ||
815 | # | ||
816 | CONFIG_USB_DEVICEFS=y | ||
817 | # CONFIG_USB_BANDWIDTH is not set | ||
818 | # CONFIG_USB_DYNAMIC_MINORS is not set | ||
819 | # CONFIG_USB_MULTITHREAD_PROBE is not set | ||
820 | # CONFIG_USB_OTG is not set | ||
821 | |||
822 | # | ||
823 | # USB Host Controller Drivers | ||
824 | # | ||
825 | # CONFIG_USB_ISP116X_HCD is not set | ||
826 | CONFIG_USB_OHCI_HCD=y | ||
827 | # CONFIG_USB_OHCI_BIG_ENDIAN is not set | ||
828 | CONFIG_USB_OHCI_LITTLE_ENDIAN=y | ||
829 | # CONFIG_USB_SL811_HCD is not set | ||
830 | |||
831 | # | ||
832 | # USB Device Class drivers | ||
833 | # | ||
834 | # CONFIG_USB_ACM is not set | ||
835 | # CONFIG_USB_PRINTER is not set | ||
836 | |||
837 | # | ||
838 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
839 | # | ||
840 | |||
841 | # | ||
842 | # may also be needed; see USB_STORAGE Help for more information | ||
843 | # | ||
844 | CONFIG_USB_STORAGE=y | ||
845 | # CONFIG_USB_STORAGE_DEBUG is not set | ||
846 | # CONFIG_USB_STORAGE_DATAFAB is not set | ||
847 | # CONFIG_USB_STORAGE_FREECOM is not set | ||
848 | # CONFIG_USB_STORAGE_DPCM is not set | ||
849 | # CONFIG_USB_STORAGE_USBAT is not set | ||
850 | # CONFIG_USB_STORAGE_SDDR09 is not set | ||
851 | # CONFIG_USB_STORAGE_SDDR55 is not set | ||
852 | # CONFIG_USB_STORAGE_JUMPSHOT is not set | ||
853 | # CONFIG_USB_STORAGE_ALAUDA is not set | ||
854 | # CONFIG_USB_STORAGE_ONETOUCH is not set | ||
855 | # CONFIG_USB_STORAGE_KARMA is not set | ||
856 | # CONFIG_USB_LIBUSUAL is not set | ||
857 | |||
858 | # | ||
859 | # USB Input Devices | ||
860 | # | ||
861 | # CONFIG_USB_HID is not set | ||
862 | |||
863 | # | ||
864 | # USB HID Boot Protocol drivers | ||
865 | # | ||
866 | # CONFIG_USB_KBD is not set | ||
867 | # CONFIG_USB_MOUSE is not set | ||
868 | # CONFIG_USB_AIPTEK is not set | ||
869 | # CONFIG_USB_WACOM is not set | ||
870 | # CONFIG_USB_ACECAD is not set | ||
871 | # CONFIG_USB_KBTAB is not set | ||
872 | # CONFIG_USB_POWERMATE is not set | ||
873 | # CONFIG_USB_TOUCHSCREEN is not set | ||
874 | # CONFIG_USB_YEALINK is not set | ||
875 | # CONFIG_USB_XPAD is not set | ||
876 | # CONFIG_USB_ATI_REMOTE is not set | ||
877 | # CONFIG_USB_ATI_REMOTE2 is not set | ||
878 | # CONFIG_USB_KEYSPAN_REMOTE is not set | ||
879 | # CONFIG_USB_APPLETOUCH is not set | ||
880 | |||
881 | # | ||
882 | # USB Imaging devices | ||
883 | # | ||
884 | # CONFIG_USB_MDC800 is not set | ||
885 | # CONFIG_USB_MICROTEK is not set | ||
886 | |||
887 | # | ||
888 | # USB Network Adapters | ||
889 | # | ||
890 | # CONFIG_USB_CATC is not set | ||
891 | # CONFIG_USB_KAWETH is not set | ||
892 | # CONFIG_USB_PEGASUS is not set | ||
893 | # CONFIG_USB_RTL8150 is not set | ||
894 | # CONFIG_USB_USBNET_MII is not set | ||
895 | # CONFIG_USB_USBNET is not set | ||
896 | CONFIG_USB_MON=y | ||
897 | |||
898 | # | ||
899 | # USB port drivers | ||
900 | # | ||
901 | |||
902 | # | ||
903 | # USB Serial Converter support | ||
904 | # | ||
905 | # CONFIG_USB_SERIAL is not set | ||
906 | |||
907 | # | ||
908 | # USB Miscellaneous drivers | ||
909 | # | ||
910 | # CONFIG_USB_EMI62 is not set | ||
911 | # CONFIG_USB_EMI26 is not set | ||
912 | # CONFIG_USB_ADUTUX is not set | ||
913 | # CONFIG_USB_AUERSWALD is not set | ||
914 | # CONFIG_USB_RIO500 is not set | ||
915 | # CONFIG_USB_LEGOTOWER is not set | ||
916 | # CONFIG_USB_LCD is not set | ||
917 | # CONFIG_USB_LED is not set | ||
918 | # CONFIG_USB_CYPRESS_CY7C63 is not set | ||
919 | # CONFIG_USB_CYTHERM is not set | ||
920 | # CONFIG_USB_PHIDGET is not set | ||
921 | # CONFIG_USB_IDMOUSE is not set | ||
922 | # CONFIG_USB_FTDI_ELAN is not set | ||
923 | # CONFIG_USB_APPLEDISPLAY is not set | ||
924 | # CONFIG_USB_LD is not set | ||
925 | # CONFIG_USB_TRANCEVIBRATOR is not set | ||
926 | # CONFIG_USB_TEST is not set | ||
927 | |||
928 | # | ||
929 | # USB DSL modem support | ||
930 | # | ||
931 | |||
932 | # | ||
933 | # USB Gadget Support | ||
934 | # | ||
935 | CONFIG_USB_GADGET=y | ||
936 | # CONFIG_USB_GADGET_DEBUG_FILES is not set | ||
937 | CONFIG_USB_GADGET_SELECTED=y | ||
938 | # CONFIG_USB_GADGET_NET2280 is not set | ||
939 | # CONFIG_USB_GADGET_PXA2XX is not set | ||
940 | # CONFIG_USB_GADGET_GOKU is not set | ||
941 | # CONFIG_USB_GADGET_LH7A40X is not set | ||
942 | # CONFIG_USB_GADGET_OMAP is not set | ||
943 | CONFIG_USB_GADGET_AT91=y | ||
944 | CONFIG_USB_AT91=y | ||
945 | # CONFIG_USB_GADGET_DUMMY_HCD is not set | ||
946 | # CONFIG_USB_GADGET_DUALSPEED is not set | ||
947 | CONFIG_USB_ZERO=m | ||
948 | # CONFIG_USB_ETH is not set | ||
949 | CONFIG_USB_GADGETFS=m | ||
950 | CONFIG_USB_FILE_STORAGE=m | ||
951 | # CONFIG_USB_FILE_STORAGE_TEST is not set | ||
952 | CONFIG_USB_G_SERIAL=m | ||
953 | # CONFIG_USB_MIDI_GADGET is not set | ||
954 | |||
955 | # | ||
956 | # MMC/SD Card support | ||
957 | # | ||
958 | CONFIG_MMC=y | ||
959 | # CONFIG_MMC_DEBUG is not set | ||
960 | CONFIG_MMC_BLOCK=y | ||
961 | CONFIG_MMC_AT91=m | ||
962 | # CONFIG_MMC_TIFM_SD is not set | ||
963 | |||
964 | # | ||
965 | # Real Time Clock | ||
966 | # | ||
967 | CONFIG_RTC_LIB=y | ||
968 | # CONFIG_RTC_CLASS is not set | ||
969 | |||
970 | # | ||
971 | # File systems | ||
972 | # | ||
973 | CONFIG_EXT2_FS=y | ||
974 | # CONFIG_EXT2_FS_XATTR is not set | ||
975 | # CONFIG_EXT2_FS_XIP is not set | ||
976 | # CONFIG_EXT3_FS is not set | ||
977 | # CONFIG_EXT4DEV_FS is not set | ||
978 | # CONFIG_REISERFS_FS is not set | ||
979 | # CONFIG_JFS_FS is not set | ||
980 | # CONFIG_FS_POSIX_ACL is not set | ||
981 | # CONFIG_XFS_FS is not set | ||
982 | # CONFIG_GFS2_FS is not set | ||
983 | # CONFIG_OCFS2_FS is not set | ||
984 | # CONFIG_MINIX_FS is not set | ||
985 | # CONFIG_ROMFS_FS is not set | ||
986 | CONFIG_INOTIFY=y | ||
987 | CONFIG_INOTIFY_USER=y | ||
988 | # CONFIG_QUOTA is not set | ||
989 | CONFIG_DNOTIFY=y | ||
990 | # CONFIG_AUTOFS_FS is not set | ||
991 | # CONFIG_AUTOFS4_FS is not set | ||
992 | # CONFIG_FUSE_FS is not set | ||
993 | |||
994 | # | ||
995 | # CD-ROM/DVD Filesystems | ||
996 | # | ||
997 | # CONFIG_ISO9660_FS is not set | ||
998 | # CONFIG_UDF_FS is not set | ||
999 | |||
1000 | # | ||
1001 | # DOS/FAT/NT Filesystems | ||
1002 | # | ||
1003 | CONFIG_FAT_FS=y | ||
1004 | # CONFIG_MSDOS_FS is not set | ||
1005 | CONFIG_VFAT_FS=y | ||
1006 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
1007 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
1008 | # CONFIG_NTFS_FS is not set | ||
1009 | |||
1010 | # | ||
1011 | # Pseudo filesystems | ||
1012 | # | ||
1013 | CONFIG_PROC_FS=y | ||
1014 | CONFIG_PROC_SYSCTL=y | ||
1015 | CONFIG_SYSFS=y | ||
1016 | CONFIG_TMPFS=y | ||
1017 | # CONFIG_TMPFS_POSIX_ACL is not set | ||
1018 | # CONFIG_HUGETLB_PAGE is not set | ||
1019 | CONFIG_RAMFS=y | ||
1020 | # CONFIG_CONFIGFS_FS is not set | ||
1021 | |||
1022 | # | ||
1023 | # Miscellaneous filesystems | ||
1024 | # | ||
1025 | # CONFIG_ADFS_FS is not set | ||
1026 | # CONFIG_AFFS_FS is not set | ||
1027 | # CONFIG_HFS_FS is not set | ||
1028 | # CONFIG_HFSPLUS_FS is not set | ||
1029 | # CONFIG_BEFS_FS is not set | ||
1030 | # CONFIG_BFS_FS is not set | ||
1031 | # CONFIG_EFS_FS is not set | ||
1032 | CONFIG_JFFS2_FS=y | ||
1033 | CONFIG_JFFS2_FS_DEBUG=0 | ||
1034 | CONFIG_JFFS2_FS_WRITEBUFFER=y | ||
1035 | # CONFIG_JFFS2_SUMMARY is not set | ||
1036 | # CONFIG_JFFS2_FS_XATTR is not set | ||
1037 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | ||
1038 | CONFIG_JFFS2_ZLIB=y | ||
1039 | CONFIG_JFFS2_RTIME=y | ||
1040 | # CONFIG_JFFS2_RUBIN is not set | ||
1041 | CONFIG_CRAMFS=y | ||
1042 | # CONFIG_VXFS_FS is not set | ||
1043 | # CONFIG_HPFS_FS is not set | ||
1044 | # CONFIG_QNX4FS_FS is not set | ||
1045 | # CONFIG_SYSV_FS is not set | ||
1046 | # CONFIG_UFS_FS is not set | ||
1047 | |||
1048 | # | ||
1049 | # Network File Systems | ||
1050 | # | ||
1051 | CONFIG_NFS_FS=y | ||
1052 | # CONFIG_NFS_V3 is not set | ||
1053 | # CONFIG_NFS_V4 is not set | ||
1054 | # CONFIG_NFS_DIRECTIO is not set | ||
1055 | # CONFIG_NFSD is not set | ||
1056 | CONFIG_ROOT_NFS=y | ||
1057 | CONFIG_LOCKD=y | ||
1058 | CONFIG_NFS_COMMON=y | ||
1059 | CONFIG_SUNRPC=y | ||
1060 | # CONFIG_RPCSEC_GSS_KRB5 is not set | ||
1061 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
1062 | # CONFIG_SMB_FS is not set | ||
1063 | # CONFIG_CIFS is not set | ||
1064 | # CONFIG_NCP_FS is not set | ||
1065 | # CONFIG_CODA_FS is not set | ||
1066 | # CONFIG_AFS_FS is not set | ||
1067 | # CONFIG_9P_FS is not set | ||
1068 | |||
1069 | # | ||
1070 | # Partition Types | ||
1071 | # | ||
1072 | # CONFIG_PARTITION_ADVANCED is not set | ||
1073 | CONFIG_MSDOS_PARTITION=y | ||
1074 | |||
1075 | # | ||
1076 | # Native Language Support | ||
1077 | # | ||
1078 | CONFIG_NLS=y | ||
1079 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
1080 | CONFIG_NLS_CODEPAGE_437=y | ||
1081 | # CONFIG_NLS_CODEPAGE_737 is not set | ||
1082 | # CONFIG_NLS_CODEPAGE_775 is not set | ||
1083 | CONFIG_NLS_CODEPAGE_850=y | ||
1084 | # CONFIG_NLS_CODEPAGE_852 is not set | ||
1085 | # CONFIG_NLS_CODEPAGE_855 is not set | ||
1086 | # CONFIG_NLS_CODEPAGE_857 is not set | ||
1087 | # CONFIG_NLS_CODEPAGE_860 is not set | ||
1088 | # CONFIG_NLS_CODEPAGE_861 is not set | ||
1089 | # CONFIG_NLS_CODEPAGE_862 is not set | ||
1090 | # CONFIG_NLS_CODEPAGE_863 is not set | ||
1091 | # CONFIG_NLS_CODEPAGE_864 is not set | ||
1092 | # CONFIG_NLS_CODEPAGE_865 is not set | ||
1093 | # CONFIG_NLS_CODEPAGE_866 is not set | ||
1094 | # CONFIG_NLS_CODEPAGE_869 is not set | ||
1095 | # CONFIG_NLS_CODEPAGE_936 is not set | ||
1096 | # CONFIG_NLS_CODEPAGE_950 is not set | ||
1097 | # CONFIG_NLS_CODEPAGE_932 is not set | ||
1098 | # CONFIG_NLS_CODEPAGE_949 is not set | ||
1099 | # CONFIG_NLS_CODEPAGE_874 is not set | ||
1100 | # CONFIG_NLS_ISO8859_8 is not set | ||
1101 | # CONFIG_NLS_CODEPAGE_1250 is not set | ||
1102 | # CONFIG_NLS_CODEPAGE_1251 is not set | ||
1103 | # CONFIG_NLS_ASCII is not set | ||
1104 | CONFIG_NLS_ISO8859_1=y | ||
1105 | # CONFIG_NLS_ISO8859_2 is not set | ||
1106 | # CONFIG_NLS_ISO8859_3 is not set | ||
1107 | # CONFIG_NLS_ISO8859_4 is not set | ||
1108 | # CONFIG_NLS_ISO8859_5 is not set | ||
1109 | # CONFIG_NLS_ISO8859_6 is not set | ||
1110 | # CONFIG_NLS_ISO8859_7 is not set | ||
1111 | # CONFIG_NLS_ISO8859_9 is not set | ||
1112 | # CONFIG_NLS_ISO8859_13 is not set | ||
1113 | # CONFIG_NLS_ISO8859_14 is not set | ||
1114 | # CONFIG_NLS_ISO8859_15 is not set | ||
1115 | # CONFIG_NLS_KOI8_R is not set | ||
1116 | # CONFIG_NLS_KOI8_U is not set | ||
1117 | # CONFIG_NLS_UTF8 is not set | ||
1118 | |||
1119 | # | ||
1120 | # Distributed Lock Manager | ||
1121 | # | ||
1122 | # CONFIG_DLM is not set | ||
1123 | |||
1124 | # | ||
1125 | # Profiling support | ||
1126 | # | ||
1127 | # CONFIG_PROFILING is not set | ||
1128 | |||
1129 | # | ||
1130 | # Kernel hacking | ||
1131 | # | ||
1132 | # CONFIG_PRINTK_TIME is not set | ||
1133 | CONFIG_ENABLE_MUST_CHECK=y | ||
1134 | # CONFIG_MAGIC_SYSRQ is not set | ||
1135 | # CONFIG_UNUSED_SYMBOLS is not set | ||
1136 | # CONFIG_DEBUG_FS is not set | ||
1137 | # CONFIG_HEADERS_CHECK is not set | ||
1138 | CONFIG_DEBUG_KERNEL=y | ||
1139 | CONFIG_LOG_BUF_SHIFT=14 | ||
1140 | CONFIG_DETECT_SOFTLOCKUP=y | ||
1141 | # CONFIG_SCHEDSTATS is not set | ||
1142 | # CONFIG_DEBUG_SLAB is not set | ||
1143 | # CONFIG_DEBUG_RT_MUTEXES is not set | ||
1144 | # CONFIG_RT_MUTEX_TESTER is not set | ||
1145 | # CONFIG_DEBUG_SPINLOCK is not set | ||
1146 | # CONFIG_DEBUG_MUTEXES is not set | ||
1147 | # CONFIG_DEBUG_RWSEMS is not set | ||
1148 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
1149 | # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set | ||
1150 | # CONFIG_DEBUG_KOBJECT is not set | ||
1151 | CONFIG_DEBUG_BUGVERBOSE=y | ||
1152 | # CONFIG_DEBUG_INFO is not set | ||
1153 | # CONFIG_DEBUG_VM is not set | ||
1154 | # CONFIG_DEBUG_LIST is not set | ||
1155 | CONFIG_FRAME_POINTER=y | ||
1156 | CONFIG_FORCED_INLINING=y | ||
1157 | # CONFIG_RCU_TORTURE_TEST is not set | ||
1158 | CONFIG_DEBUG_USER=y | ||
1159 | # CONFIG_DEBUG_ERRORS is not set | ||
1160 | CONFIG_DEBUG_LL=y | ||
1161 | # CONFIG_DEBUG_ICEDCC is not set | ||
1162 | |||
1163 | # | ||
1164 | # Security options | ||
1165 | # | ||
1166 | # CONFIG_KEYS is not set | ||
1167 | # CONFIG_SECURITY is not set | ||
1168 | |||
1169 | # | ||
1170 | # Cryptographic options | ||
1171 | # | ||
1172 | # CONFIG_CRYPTO is not set | ||
1173 | |||
1174 | # | ||
1175 | # Library routines | ||
1176 | # | ||
1177 | CONFIG_BITREVERSE=y | ||
1178 | # CONFIG_CRC_CCITT is not set | ||
1179 | # CONFIG_CRC16 is not set | ||
1180 | CONFIG_CRC32=y | ||
1181 | # CONFIG_LIBCRC32C is not set | ||
1182 | CONFIG_ZLIB_INFLATE=y | ||
1183 | CONFIG_PLIST=y | ||
1184 | CONFIG_IOMAP_COPY=y | ||
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig index 3de5c643848c..baa97698c744 100644 --- a/arch/arm/configs/ateb9200_defconfig +++ b/arch/arm/configs/ateb9200_defconfig | |||
@@ -1066,7 +1066,7 @@ CONFIG_RTC_INTF_DEV=y | |||
1066 | # CONFIG_RTC_DRV_PCF8563 is not set | 1066 | # CONFIG_RTC_DRV_PCF8563 is not set |
1067 | # CONFIG_RTC_DRV_RS5C372 is not set | 1067 | # CONFIG_RTC_DRV_RS5C372 is not set |
1068 | # CONFIG_RTC_DRV_M48T86 is not set | 1068 | # CONFIG_RTC_DRV_M48T86 is not set |
1069 | CONFIG_RTC_DRV_AT91=y | 1069 | CONFIG_RTC_DRV_AT91RM9200=y |
1070 | # CONFIG_RTC_DRV_TEST is not set | 1070 | # CONFIG_RTC_DRV_TEST is not set |
1071 | 1071 | ||
1072 | # | 1072 | # |
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig index 2cadd51506bb..88e5d28aeec7 100644 --- a/arch/arm/configs/csb337_defconfig +++ b/arch/arm/configs/csb337_defconfig | |||
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y | |||
355 | # Mapping drivers for chip access | 355 | # Mapping drivers for chip access |
356 | # | 356 | # |
357 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | 357 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set |
358 | # CONFIG_MTD_PHYSMAP is not set | 358 | CONFIG_MTD_PHYSMAP=y |
359 | CONFIG_MTD_PHYSMAP_START=0 | ||
360 | CONFIG_MTD_PHYSMAP_LEN=0 | ||
361 | CONFIG_MTD_PHYSMAP_BANKWIDTH=0 | ||
359 | # CONFIG_MTD_ARM_INTEGRATOR is not set | 362 | # CONFIG_MTD_ARM_INTEGRATOR is not set |
360 | # CONFIG_MTD_PLATRAM is not set | 363 | # CONFIG_MTD_PLATRAM is not set |
361 | CONFIG_MTD_CSB337=y | ||
362 | 364 | ||
363 | # | 365 | # |
364 | # Self-contained MTD device drivers | 366 | # Self-contained MTD device drivers |
@@ -986,7 +988,7 @@ CONFIG_RTC_DRV_DS1307=y | |||
986 | # CONFIG_RTC_DRV_PCF8583 is not set | 988 | # CONFIG_RTC_DRV_PCF8583 is not set |
987 | # CONFIG_RTC_DRV_RS5C372 is not set | 989 | # CONFIG_RTC_DRV_RS5C372 is not set |
988 | # CONFIG_RTC_DRV_M48T86 is not set | 990 | # CONFIG_RTC_DRV_M48T86 is not set |
989 | CONFIG_RTC_DRV_AT91=y | 991 | CONFIG_RTC_DRV_AT91RM9200=y |
990 | # CONFIG_RTC_DRV_TEST is not set | 992 | # CONFIG_RTC_DRV_TEST is not set |
991 | # CONFIG_RTC_DRV_V3020 is not set | 993 | # CONFIG_RTC_DRV_V3020 is not set |
992 | 994 | ||
diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig index 94908c1df4cf..669f035896f9 100644 --- a/arch/arm/configs/csb637_defconfig +++ b/arch/arm/configs/csb637_defconfig | |||
@@ -355,10 +355,12 @@ CONFIG_MTD_CFI_UTIL=y | |||
355 | # Mapping drivers for chip access | 355 | # Mapping drivers for chip access |
356 | # | 356 | # |
357 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set | 357 | # CONFIG_MTD_COMPLEX_MAPPINGS is not set |
358 | # CONFIG_MTD_PHYSMAP is not set | 358 | CONFIG_MTD_PHYSMAP=y |
359 | CONFIG_MTD_PHYSMAP_START=0 | ||
360 | CONFIG_MTD_PHYSMAP_LEN=0 | ||
361 | CONFIG_MTD_PHYSMAP_BANKWIDTH=0 | ||
359 | # CONFIG_MTD_ARM_INTEGRATOR is not set | 362 | # CONFIG_MTD_ARM_INTEGRATOR is not set |
360 | # CONFIG_MTD_PLATRAM is not set | 363 | # CONFIG_MTD_PLATRAM is not set |
361 | CONFIG_MTD_CSB637=y | ||
362 | 364 | ||
363 | # | 365 | # |
364 | # Self-contained MTD device drivers | 366 | # Self-contained MTD device drivers |
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig index a4cdafc1548a..a0f48d54fbcc 100644 --- a/arch/arm/configs/kafa_defconfig +++ b/arch/arm/configs/kafa_defconfig | |||
@@ -718,7 +718,7 @@ CONFIG_RTC_INTF_DEV=y | |||
718 | # CONFIG_RTC_DRV_PCF8563 is not set | 718 | # CONFIG_RTC_DRV_PCF8563 is not set |
719 | # CONFIG_RTC_DRV_RS5C372 is not set | 719 | # CONFIG_RTC_DRV_RS5C372 is not set |
720 | # CONFIG_RTC_DRV_M48T86 is not set | 720 | # CONFIG_RTC_DRV_M48T86 is not set |
721 | CONFIG_RTC_DRV_AT91=y | 721 | CONFIG_RTC_DRV_AT91RM9200=y |
722 | # CONFIG_RTC_DRV_TEST is not set | 722 | # CONFIG_RTC_DRV_TEST is not set |
723 | 723 | ||
724 | # | 724 | # |
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 3b31a33d0080..df19e3632038 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.19-rc4 | 3 | # Linux kernel version: 2.6.20 |
4 | # Fri Nov 3 17:41:31 2006 | 4 | # Thu Feb 15 11:26:24 2007 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_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 | |||
11 | CONFIG_HARDIRQS_SW_RESEND=y | 11 | CONFIG_HARDIRQS_SW_RESEND=y |
12 | CONFIG_GENERIC_IRQ_PROBE=y | 12 | CONFIG_GENERIC_IRQ_PROBE=y |
13 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | 13 | CONFIG_RWSEM_GENERIC_SPINLOCK=y |
14 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set | ||
15 | # CONFIG_ARCH_HAS_ILOG2_U64 is not set | ||
14 | CONFIG_GENERIC_HWEIGHT=y | 16 | CONFIG_GENERIC_HWEIGHT=y |
15 | CONFIG_GENERIC_CALIBRATE_DELAY=y | 17 | CONFIG_GENERIC_CALIBRATE_DELAY=y |
16 | CONFIG_VECTORS_BASE=0xffff0000 | 18 | CONFIG_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 |
42 | CONFIG_SYSFS_DEPRECATED=y | ||
40 | # CONFIG_RELAY is not set | 43 | # CONFIG_RELAY is not set |
41 | CONFIG_INITRAMFS_SOURCE="" | 44 | CONFIG_INITRAMFS_SOURCE="" |
42 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 45 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
43 | CONFIG_SYSCTL=y | 46 | CONFIG_SYSCTL=y |
44 | # CONFIG_EMBEDDED is not set | 47 | # CONFIG_EMBEDDED is not set |
45 | CONFIG_UID16=y | 48 | CONFIG_UID16=y |
46 | # CONFIG_SYSCTL_SYSCALL is not set | 49 | CONFIG_SYSCTL_SYSCALL=y |
47 | CONFIG_KALLSYMS=y | 50 | CONFIG_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 | # |
78 | CONFIG_BLOCK=y | 81 | CONFIG_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 |
131 | CONFIG_PLAT_S3C24XX=y | ||
132 | CONFIG_CPU_S3C244X=y | ||
133 | CONFIG_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 | ||
138 | CONFIG_S3C2410_LOWLEVEL_UART_PORT=0 | ||
139 | CONFIG_S3C2410_DMA=y | ||
140 | # CONFIG_S3C2410_DMA_DEBUG is not set | ||
141 | CONFIG_MACH_SMDK=y | ||
125 | 142 | ||
126 | # | 143 | # |
127 | # S3C24XX Implementations | 144 | # S3C2400 Machines |
128 | # | 145 | # |
129 | # CONFIG_MACH_AML_M5900 is not set | 146 | CONFIG_CPU_S3C2410=y |
130 | CONFIG_MACH_ANUBIS=y | 147 | CONFIG_CPU_S3C2410_DMA=y |
131 | CONFIG_MACH_OSIRIS=y | 148 | CONFIG_S3C2410_PM=y |
132 | CONFIG_ARCH_BAST=y | 149 | CONFIG_S3C2410_GPIO=y |
133 | CONFIG_BAST_PC104_IRQ=y | 150 | CONFIG_S3C2410_CLOCK=y |
151 | |||
152 | # | ||
153 | # S3C2410 Machines | ||
154 | # | ||
155 | CONFIG_ARCH_SMDK2410=y | ||
134 | CONFIG_ARCH_H1940=y | 156 | CONFIG_ARCH_H1940=y |
157 | CONFIG_PM_H1940=y | ||
135 | CONFIG_MACH_N30=y | 158 | CONFIG_MACH_N30=y |
136 | CONFIG_MACH_SMDK=y | 159 | CONFIG_ARCH_BAST=y |
137 | CONFIG_ARCH_SMDK2410=y | ||
138 | CONFIG_ARCH_S3C2440=y | ||
139 | CONFIG_SMDK2440_CPU2440=y | ||
140 | CONFIG_SMDK2440_CPU2442=y | ||
141 | CONFIG_MACH_S3C2413=y | ||
142 | CONFIG_MACH_SMDK2413=y | ||
143 | CONFIG_MACH_VR1000=y | ||
144 | CONFIG_MACH_RX3715=y | ||
145 | CONFIG_MACH_OTOM=y | 160 | CONFIG_MACH_OTOM=y |
146 | CONFIG_MACH_NEXCODER_2440=y | 161 | CONFIG_MACH_AML_M5900=y |
147 | CONFIG_MACH_VSTMS=y | 162 | CONFIG_BAST_PC104_IRQ=y |
148 | CONFIG_S3C2410_CLOCK=y | 163 | CONFIG_MACH_VR1000=y |
149 | CONFIG_S3C2410_PM=y | ||
150 | CONFIG_CPU_S3C2410_DMA=y | ||
151 | CONFIG_CPU_S3C2410=y | ||
152 | CONFIG_S3C2412_PM=y | ||
153 | CONFIG_CPU_S3C2412=y | 164 | CONFIG_CPU_S3C2412=y |
154 | CONFIG_CPU_S3C244X=y | 165 | CONFIG_S3C2412_DMA=y |
166 | CONFIG_S3C2412_PM=y | ||
167 | |||
168 | # | ||
169 | # S3C2412 Machines | ||
170 | # | ||
171 | CONFIG_MACH_SMDK2413=y | ||
172 | CONFIG_MACH_S3C2413=y | ||
173 | CONFIG_MACH_VSTMS=y | ||
155 | CONFIG_CPU_S3C2440=y | 174 | CONFIG_CPU_S3C2440=y |
175 | CONFIG_S3C2440_DMA=y | ||
176 | |||
177 | # | ||
178 | # S3C2440 Machines | ||
179 | # | ||
180 | CONFIG_MACH_ANUBIS=y | ||
181 | CONFIG_MACH_OSIRIS=y | ||
182 | CONFIG_MACH_RX3715=y | ||
183 | CONFIG_ARCH_S3C2440=y | ||
184 | CONFIG_MACH_NEXCODER_2440=y | ||
185 | CONFIG_SMDK2440_CPU2440=y | ||
156 | CONFIG_CPU_S3C2442=y | 186 | CONFIG_CPU_S3C2442=y |
157 | 187 | ||
158 | # | 188 | # |
159 | # S3C2410 Boot | 189 | # S3C2442 Machines |
160 | # | 190 | # |
161 | # CONFIG_S3C2410_BOOT_WATCHDOG is not set | 191 | CONFIG_SMDK2440_CPU2442=y |
162 | # CONFIG_S3C2410_BOOT_ERROR_RESET is not set | 192 | CONFIG_CPU_S3C2443=y |
163 | 193 | ||
164 | # | 194 | # |
165 | # S3C2410 Setup | 195 | # S3C2443 Machines |
166 | # | 196 | # |
167 | CONFIG_S3C2410_DMA=y | 197 | CONFIG_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 | ||
171 | CONFIG_PM_SIMTEC=y | ||
172 | CONFIG_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 |
304 | CONFIG_TCP_CONG_CUBIC=y | 330 | CONFIG_TCP_CONG_CUBIC=y |
305 | CONFIG_DEFAULT_TCP_CONG="cubic" | 331 | CONFIG_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 | # |
387 | CONFIG_MTD_CHAR=y | 414 | CONFIG_MTD_CHAR=y |
415 | CONFIG_MTD_BLKDEVS=y | ||
388 | CONFIG_MTD_BLOCK=y | 416 | CONFIG_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 | |||
700 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | 733 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 |
701 | CONFIG_SERIAL_8250_EXTENDED=y | 734 | CONFIG_SERIAL_8250_EXTENDED=y |
702 | CONFIG_SERIAL_8250_MANY_PORTS=y | 735 | CONFIG_SERIAL_8250_MANY_PORTS=y |
703 | CONFIG_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 |
741 | CONFIG_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 | # | ||
989 | CONFIG_HID=y | ||
990 | |||
991 | # | ||
955 | # USB support | 992 | # USB support |
956 | # | 993 | # |
957 | CONFIG_USB_ARCH_HAS_HCD=y | 994 | CONFIG_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 |
1032 | CONFIG_USB_MON=y | 1070 | CONFIG_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 |
1182 | CONFIG_JFFS_FS=y | ||
1183 | CONFIG_JFFS_FS_VERBOSE=0 | ||
1184 | # CONFIG_JFFS_PROC_FS is not set | ||
1185 | CONFIG_JFFS2_FS=y | 1220 | CONFIG_JFFS2_FS=y |
1186 | CONFIG_JFFS2_FS_DEBUG=0 | 1221 | CONFIG_JFFS2_FS_DEBUG=0 |
1187 | CONFIG_JFFS2_FS_WRITEBUFFER=y | 1222 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
@@ -1191,7 +1226,7 @@ CONFIG_JFFS2_FS_WRITEBUFFER=y | |||
1191 | CONFIG_JFFS2_ZLIB=y | 1226 | CONFIG_JFFS2_ZLIB=y |
1192 | CONFIG_JFFS2_RTIME=y | 1227 | CONFIG_JFFS2_RTIME=y |
1193 | # CONFIG_JFFS2_RUBIN is not set | 1228 | # CONFIG_JFFS2_RUBIN is not set |
1194 | # CONFIG_CRAMFS is not set | 1229 | CONFIG_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" | |||
1296 | CONFIG_ENABLE_MUST_CHECK=y | 1336 | CONFIG_ENABLE_MUST_CHECK=y |
1297 | CONFIG_MAGIC_SYSRQ=y | 1337 | CONFIG_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 | ||
1299 | CONFIG_DEBUG_KERNEL=y | 1341 | CONFIG_DEBUG_KERNEL=y |
1300 | CONFIG_LOG_BUF_SHIFT=16 | 1342 | CONFIG_LOG_BUF_SHIFT=16 |
1301 | CONFIG_DETECT_SOFTLOCKUP=y | 1343 | CONFIG_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 |
1312 | CONFIG_DEBUG_BUGVERBOSE=y | 1354 | CONFIG_DEBUG_BUGVERBOSE=y |
1313 | CONFIG_DEBUG_INFO=y | 1355 | CONFIG_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 |
1317 | CONFIG_FRAME_POINTER=y | 1358 | CONFIG_FRAME_POINTER=y |
1318 | CONFIG_FORCED_INLINING=y | 1359 | CONFIG_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 |
1321 | CONFIG_DEBUG_USER=y | 1361 | CONFIG_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 | # |
1382 | CONFIG_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 |
1344 | CONFIG_CRC32=y | 1385 | CONFIG_CRC32=y |
@@ -1346,3 +1387,4 @@ CONFIG_CRC32=y | |||
1346 | CONFIG_ZLIB_INFLATE=y | 1387 | CONFIG_ZLIB_INFLATE=y |
1347 | CONFIG_ZLIB_DEFLATE=y | 1388 | CONFIG_ZLIB_DEFLATE=y |
1348 | CONFIG_PLIST=y | 1389 | CONFIG_PLIST=y |
1390 | CONFIG_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 | |||
19 | obj-$(CONFIG_ISA_DMA) += dma-isa.o | 19 | obj-$(CONFIG_ISA_DMA) += dma-isa.o |
20 | obj-$(CONFIG_PCI) += bios32.o isa.o | 20 | obj-$(CONFIG_PCI) += bios32.o isa.o |
21 | obj-$(CONFIG_SMP) += smp.o | 21 | obj-$(CONFIG_SMP) += smp.o |
22 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | ||
22 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o | 23 | obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o |
23 | 24 | ||
24 | obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o | 25 | obj-$(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 = { | |||
75 | static int __init crunch_init(void) | 75 | static 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 | |||
16 | const extern unsigned char relocate_new_kernel[]; | ||
17 | const extern unsigned int relocate_new_kernel_size; | ||
18 | |||
19 | extern void setup_mm_for_reboot(char mode); | ||
20 | |||
21 | extern unsigned long kexec_start_address; | ||
22 | extern unsigned long kexec_indirection_page; | ||
23 | extern 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 | |||
30 | int machine_kexec_prepare(struct kimage *image) | ||
31 | { | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | void machine_kexec_cleanup(struct kimage *image) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | void machine_shutdown(void) | ||
40 | { | ||
41 | } | ||
42 | |||
43 | void machine_crash_shutdown(struct pt_regs *regs) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | void 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 | ||
8 | relocate_new_kernel: | ||
9 | |||
10 | ldr r0,kexec_indirection_page | ||
11 | ldr r1,kexec_start_address | ||
12 | |||
13 | |||
14 | 0: /* 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 | ||
22 | 1: | ||
23 | /* Is it an indirection page */ | ||
24 | tst r3,#2,0 | ||
25 | beq 1f | ||
26 | bic r0,r3,#2 | ||
27 | b 0b | ||
28 | 1: | ||
29 | |||
30 | /* are we done ? */ | ||
31 | tst r3,#4,0 | ||
32 | beq 1f | ||
33 | b 2f | ||
34 | |||
35 | 1: | ||
36 | /* is it source ? */ | ||
37 | tst r3,#8,0 | ||
38 | beq 0b | ||
39 | bic r3,r3,#8 | ||
40 | mov r6,#1024 | ||
41 | 9: | ||
42 | ldr r5,[r3],#4 | ||
43 | str r5,[r4],#4 | ||
44 | subs r6,r6,#1 | ||
45 | bne 9b | ||
46 | b 0b | ||
47 | |||
48 | 2: | ||
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 | ||
57 | kexec_start_address: | ||
58 | .long 0x0 | ||
59 | |||
60 | .globl kexec_indirection_page | ||
61 | kexec_indirection_page: | ||
62 | .long 0x0 | ||
63 | |||
64 | .globl kexec_mach_type | ||
65 | kexec_mach_type: | ||
66 | .long 0x0 | ||
67 | |||
68 | relocate_new_kernel_end: | ||
69 | |||
70 | .globl relocate_new_kernel_size | ||
71 | relocate_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 |
89 | struct cpu_cache_fns cpu_cache; | 89 | struct cpu_cache_fns cpu_cache; |
90 | #endif | 90 | #endif |
91 | #ifdef CONFIG_OUTER_CACHE | ||
92 | struct outer_cache_fns outer_cache; | ||
93 | #endif | ||
91 | 94 | ||
92 | struct stack { | 95 | struct 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 | */ |
41 | struct sys_timer *system_timer; | 41 | struct 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 */ |
44 | DEFINE_SPINLOCK(rtc_lock); | 45 | DEFINE_SPINLOCK(rtc_lock); |
45 | 46 | ||
46 | #ifdef CONFIG_SA1100_RTC_MODULE | 47 | #ifdef CONFIG_RTC_DRV_CMOS_MODULE |
47 | EXPORT_SYMBOL(rtc_lock); | 48 | EXPORT_SYMBOL(rtc_lock); |
48 | #endif | 49 | #endif |
50 | #endif /* pc-style 'CMOS' RTC support */ | ||
49 | 51 | ||
50 | /* change this if you have some constant time drift */ | 52 | /* change this if you have some constant time drift */ |
51 | #define USECS_PER_JIFFY (1000000/HZ) | 53 | #define USECS_PER_JIFFY (1000000/HZ) |
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91/Kconfig index 9f11db8af233..bf0d96272e3a 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91/Kconfig | |||
@@ -9,11 +9,14 @@ config ARCH_AT91RM9200 | |||
9 | bool "AT91RM9200" | 9 | bool "AT91RM9200" |
10 | 10 | ||
11 | config ARCH_AT91SAM9260 | 11 | config ARCH_AT91SAM9260 |
12 | bool "AT91SAM9260" | 12 | bool "AT91SAM9260 or AT91SAM9XE" |
13 | 13 | ||
14 | config ARCH_AT91SAM9261 | 14 | config ARCH_AT91SAM9261 |
15 | bool "AT91SAM9261" | 15 | bool "AT91SAM9261" |
16 | 16 | ||
17 | config ARCH_AT91SAM9263 | ||
18 | bool "AT91SAM9263" | ||
19 | |||
17 | endchoice | 20 | endchoice |
18 | 21 | ||
19 | # ---------------------------------------------------------- | 22 | # ---------------------------------------------------------- |
@@ -90,13 +93,22 @@ endif | |||
90 | 93 | ||
91 | if ARCH_AT91SAM9260 | 94 | if ARCH_AT91SAM9260 |
92 | 95 | ||
93 | comment "AT91SAM9260 Board Type" | 96 | comment "AT91SAM9260 Variants" |
97 | |||
98 | config ARCH_AT91SAM9260_SAM9XE | ||
99 | bool "AT91SAM9XE" | ||
100 | depends on ARCH_AT91SAM9260 | ||
101 | help | ||
102 | Select this if you are using Atmel's AT91SAM9XE System-on-Chip. | ||
103 | They are basicaly AT91SAM9260s with various sizes of embedded Flash. | ||
104 | |||
105 | comment "AT91SAM9260 / AT91SAM9XE Board Type" | ||
94 | 106 | ||
95 | config MACH_AT91SAM9260EK | 107 | config MACH_AT91SAM9260EK |
96 | bool "Atmel AT91SAM9260-EK Evaluation Kit" | 108 | bool "Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit" |
97 | depends on ARCH_AT91SAM9260 | 109 | depends on ARCH_AT91SAM9260 |
98 | help | 110 | help |
99 | Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit. | 111 | Select this if you are using Atmel's AT91SAM9260-EK or AT91SAM9XE Evaluation Kit |
100 | <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933> | 112 | <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933> |
101 | 113 | ||
102 | endif | 114 | endif |
@@ -118,17 +130,32 @@ endif | |||
118 | 130 | ||
119 | # ---------------------------------------------------------- | 131 | # ---------------------------------------------------------- |
120 | 132 | ||
133 | if ARCH_AT91SAM9263 | ||
134 | |||
135 | comment "AT91SAM9263 Board Type" | ||
136 | |||
137 | config MACH_AT91SAM9263EK | ||
138 | bool "Atmel AT91SAM9263-EK Evaluation Kit" | ||
139 | depends on ARCH_AT91SAM9263 | ||
140 | help | ||
141 | Select this if you are using Atmel's AT91SAM9263-EK Evaluation Kit. | ||
142 | <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4057> | ||
143 | |||
144 | endif | ||
145 | |||
146 | # ---------------------------------------------------------- | ||
147 | |||
121 | comment "AT91 Board Options" | 148 | comment "AT91 Board Options" |
122 | 149 | ||
123 | config MTD_AT91_DATAFLASH_CARD | 150 | config MTD_AT91_DATAFLASH_CARD |
124 | bool "Enable DataFlash Card support" | 151 | bool "Enable DataFlash Card support" |
125 | depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK) | 152 | depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK) |
126 | help | 153 | help |
127 | Enable support for the DataFlash card. | 154 | Enable support for the DataFlash card. |
128 | 155 | ||
129 | config MTD_NAND_AT91_BUSWIDTH_16 | 156 | config MTD_NAND_AT91_BUSWIDTH_16 |
130 | bool "Enable 16-bit data bus interface to NAND flash" | 157 | bool "Enable 16-bit data bus interface to NAND flash" |
131 | depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK) | 158 | depends on (MACH_AT91SAM9260EK || MACH_AT91SAM9261EK || MACH_AT91SAM9263EK) |
132 | help | 159 | help |
133 | On AT91SAM926x boards both types of NAND flash can be present | 160 | On AT91SAM926x boards both types of NAND flash can be present |
134 | (8 and 16 bit data bus width). | 161 | (8 and 16 bit data bus width). |
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91/Makefile index cf777007847a..05de6cdc88f1 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_PM) += pm.o | |||
13 | obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o | 13 | obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o |
14 | obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o | 14 | obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o |
15 | obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o | 15 | obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o |
16 | obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o | ||
16 | 17 | ||
17 | # AT91RM9200 board-specific support | 18 | # AT91RM9200 board-specific support |
18 | obj-$(CONFIG_MACH_ONEARM) += board-1arm.o | 19 | obj-$(CONFIG_MACH_ONEARM) += board-1arm.o |
@@ -31,6 +32,9 @@ obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o | |||
31 | # AT91SAM9261 board-specific support | 32 | # AT91SAM9261 board-specific support |
32 | obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o | 33 | obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o |
33 | 34 | ||
35 | # AT91SAM9263 board-specific support | ||
36 | obj-$(CONFIG_MACH_AT91SAM9263EK) += board-sam9263ek.o | ||
37 | |||
34 | # LEDs support | 38 | # LEDs support |
35 | led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o | 39 | led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o |
36 | led-$(CONFIG_MACH_AT91RM9200EK) += leds.o | 40 | led-$(CONFIG_MACH_AT91RM9200EK) += leds.o |
diff --git a/arch/arm/mach-at91rm9200/Makefile.boot b/arch/arm/mach-at91/Makefile.boot index e667dcc7cd34..e667dcc7cd34 100644 --- a/arch/arm/mach-at91rm9200/Makefile.boot +++ b/arch/arm/mach-at91/Makefile.boot | |||
diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c index a92e9a495b07..2ddcdd69df7d 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200.c +++ b/arch/arm/mach-at91/at91rm9200.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-at91rm9200/at91rm9200.c | 2 | * arch/arm/mach-at91/at91rm9200.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * | 5 | * |
@@ -117,6 +117,36 @@ static struct clk pioD_clk = { | |||
117 | .pmc_mask = 1 << AT91RM9200_ID_PIOD, | 117 | .pmc_mask = 1 << AT91RM9200_ID_PIOD, |
118 | .type = CLK_TYPE_PERIPHERAL, | 118 | .type = CLK_TYPE_PERIPHERAL, |
119 | }; | 119 | }; |
120 | static struct clk tc0_clk = { | ||
121 | .name = "tc0_clk", | ||
122 | .pmc_mask = 1 << AT91RM9200_ID_TC0, | ||
123 | .type = CLK_TYPE_PERIPHERAL, | ||
124 | }; | ||
125 | static struct clk tc1_clk = { | ||
126 | .name = "tc1_clk", | ||
127 | .pmc_mask = 1 << AT91RM9200_ID_TC1, | ||
128 | .type = CLK_TYPE_PERIPHERAL, | ||
129 | }; | ||
130 | static struct clk tc2_clk = { | ||
131 | .name = "tc2_clk", | ||
132 | .pmc_mask = 1 << AT91RM9200_ID_TC2, | ||
133 | .type = CLK_TYPE_PERIPHERAL, | ||
134 | }; | ||
135 | static struct clk tc3_clk = { | ||
136 | .name = "tc3_clk", | ||
137 | .pmc_mask = 1 << AT91RM9200_ID_TC3, | ||
138 | .type = CLK_TYPE_PERIPHERAL, | ||
139 | }; | ||
140 | static struct clk tc4_clk = { | ||
141 | .name = "tc4_clk", | ||
142 | .pmc_mask = 1 << AT91RM9200_ID_TC4, | ||
143 | .type = CLK_TYPE_PERIPHERAL, | ||
144 | }; | ||
145 | static struct clk tc5_clk = { | ||
146 | .name = "tc5_clk", | ||
147 | .pmc_mask = 1 << AT91RM9200_ID_TC5, | ||
148 | .type = CLK_TYPE_PERIPHERAL, | ||
149 | }; | ||
120 | 150 | ||
121 | static struct clk *periph_clocks[] __initdata = { | 151 | static struct clk *periph_clocks[] __initdata = { |
122 | &pioA_clk, | 152 | &pioA_clk, |
@@ -132,7 +162,12 @@ static struct clk *periph_clocks[] __initdata = { | |||
132 | &twi_clk, | 162 | &twi_clk, |
133 | &spi_clk, | 163 | &spi_clk, |
134 | // ssc 0 .. ssc2 | 164 | // ssc 0 .. ssc2 |
135 | // tc0 .. tc5 | 165 | &tc0_clk, |
166 | &tc1_clk, | ||
167 | &tc2_clk, | ||
168 | &tc3_clk, | ||
169 | &tc4_clk, | ||
170 | &tc5_clk, | ||
136 | &ohci_clk, | 171 | &ohci_clk, |
137 | ðer_clk, | 172 | ðer_clk, |
138 | // irq0 .. irq6 | 173 | // irq0 .. irq6 |
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 57fac7203fe4..2624a4f22d61 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-at91rm9200/at91rm9200_devices.c | 2 | * arch/arm/mach-at91/at91rm9200_devices.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> | 4 | * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> |
5 | * Copyright (C) 2005 David Brownell | 5 | * Copyright (C) 2005 David Brownell |
@@ -315,7 +315,7 @@ static struct platform_device at91rm9200_mmc_device = { | |||
315 | .num_resources = ARRAY_SIZE(mmc_resources), | 315 | .num_resources = ARRAY_SIZE(mmc_resources), |
316 | }; | 316 | }; |
317 | 317 | ||
318 | void __init at91_add_device_mmc(struct at91_mmc_data *data) | 318 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) |
319 | { | 319 | { |
320 | if (!data) | 320 | if (!data) |
321 | return; | 321 | return; |
@@ -361,7 +361,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) | |||
361 | platform_device_register(&at91rm9200_mmc_device); | 361 | platform_device_register(&at91rm9200_mmc_device); |
362 | } | 362 | } |
363 | #else | 363 | #else |
364 | void __init at91_add_device_mmc(struct at91_mmc_data *data) {} | 364 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} |
365 | #endif | 365 | #endif |
366 | 366 | ||
367 | 367 | ||
@@ -594,6 +594,10 @@ u8 at91_leds_timer; | |||
594 | 594 | ||
595 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) | 595 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) |
596 | { | 596 | { |
597 | /* Enable GPIO to access the LEDs */ | ||
598 | at91_set_gpio_output(cpu_led, 1); | ||
599 | at91_set_gpio_output(timer_led, 1); | ||
600 | |||
597 | at91_leds_cpu = cpu_led; | 601 | at91_leds_cpu = cpu_led; |
598 | at91_leds_timer = timer_led; | 602 | at91_leds_timer = timer_led; |
599 | } | 603 | } |
diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index b999e192a7e9..949199a244c7 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c | 2 | * linux/arch/arm/mach-at91/at91rm9200_time.c |
3 | * | 3 | * |
4 | * Copyright (C) 2003 SAN People | 4 | * Copyright (C) 2003 SAN People |
5 | * Copyright (C) 2003 ATMEL | 5 | * Copyright (C) 2003 ATMEL |
diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index b14871adc300..6ea41d8266cb 100644 --- a/arch/arm/mach-at91rm9200/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-at91rm9200/at91sam9260.c | 2 | * arch/arm/mach-at91/at91sam9260.c |
3 | * | 3 | * |
4 | * Copyright (C) 2006 SAN People | 4 | * Copyright (C) 2006 SAN People |
5 | * | 5 | * |
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <asm/mach/arch.h> | 15 | #include <asm/mach/arch.h> |
16 | #include <asm/mach/map.h> | 16 | #include <asm/mach/map.h> |
17 | #include <asm/arch/cpu.h> | ||
17 | #include <asm/arch/at91sam9260.h> | 18 | #include <asm/arch/at91sam9260.h> |
18 | #include <asm/arch/at91_pmc.h> | 19 | #include <asm/arch/at91_pmc.h> |
19 | #include <asm/arch/at91_rstc.h> | 20 | #include <asm/arch/at91_rstc.h> |
@@ -27,7 +28,11 @@ static struct map_desc at91sam9260_io_desc[] __initdata = { | |||
27 | .pfn = __phys_to_pfn(AT91_BASE_SYS), | 28 | .pfn = __phys_to_pfn(AT91_BASE_SYS), |
28 | .length = SZ_16K, | 29 | .length = SZ_16K, |
29 | .type = MT_DEVICE, | 30 | .type = MT_DEVICE, |
30 | }, { | 31 | } |
32 | }; | ||
33 | |||
34 | static struct map_desc at91sam9260_sram_desc[] __initdata = { | ||
35 | { | ||
31 | .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE, | 36 | .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE, |
32 | .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE), | 37 | .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE), |
33 | .length = AT91SAM9260_SRAM0_SIZE, | 38 | .length = AT91SAM9260_SRAM0_SIZE, |
@@ -37,7 +42,14 @@ static struct map_desc at91sam9260_io_desc[] __initdata = { | |||
37 | .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE), | 42 | .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE), |
38 | .length = AT91SAM9260_SRAM1_SIZE, | 43 | .length = AT91SAM9260_SRAM1_SIZE, |
39 | .type = MT_DEVICE, | 44 | .type = MT_DEVICE, |
40 | }, | 45 | } |
46 | }; | ||
47 | |||
48 | static struct map_desc at91sam9xe_sram_desc[] __initdata = { | ||
49 | { | ||
50 | .pfn = __phys_to_pfn(AT91SAM9XE_SRAM_BASE), | ||
51 | .type = MT_DEVICE, | ||
52 | } | ||
41 | }; | 53 | }; |
42 | 54 | ||
43 | /* -------------------------------------------------------------------- | 55 | /* -------------------------------------------------------------------- |
@@ -107,13 +119,28 @@ static struct clk spi1_clk = { | |||
107 | .pmc_mask = 1 << AT91SAM9260_ID_SPI1, | 119 | .pmc_mask = 1 << AT91SAM9260_ID_SPI1, |
108 | .type = CLK_TYPE_PERIPHERAL, | 120 | .type = CLK_TYPE_PERIPHERAL, |
109 | }; | 121 | }; |
122 | static struct clk tc0_clk = { | ||
123 | .name = "tc0_clk", | ||
124 | .pmc_mask = 1 << AT91SAM9260_ID_TC0, | ||
125 | .type = CLK_TYPE_PERIPHERAL, | ||
126 | }; | ||
127 | static struct clk tc1_clk = { | ||
128 | .name = "tc1_clk", | ||
129 | .pmc_mask = 1 << AT91SAM9260_ID_TC1, | ||
130 | .type = CLK_TYPE_PERIPHERAL, | ||
131 | }; | ||
132 | static struct clk tc2_clk = { | ||
133 | .name = "tc2_clk", | ||
134 | .pmc_mask = 1 << AT91SAM9260_ID_TC2, | ||
135 | .type = CLK_TYPE_PERIPHERAL, | ||
136 | }; | ||
110 | static struct clk ohci_clk = { | 137 | static struct clk ohci_clk = { |
111 | .name = "ohci_clk", | 138 | .name = "ohci_clk", |
112 | .pmc_mask = 1 << AT91SAM9260_ID_UHP, | 139 | .pmc_mask = 1 << AT91SAM9260_ID_UHP, |
113 | .type = CLK_TYPE_PERIPHERAL, | 140 | .type = CLK_TYPE_PERIPHERAL, |
114 | }; | 141 | }; |
115 | static struct clk ether_clk = { | 142 | static struct clk macb_clk = { |
116 | .name = "ether_clk", | 143 | .name = "macb_clk", |
117 | .pmc_mask = 1 << AT91SAM9260_ID_EMAC, | 144 | .pmc_mask = 1 << AT91SAM9260_ID_EMAC, |
118 | .type = CLK_TYPE_PERIPHERAL, | 145 | .type = CLK_TYPE_PERIPHERAL, |
119 | }; | 146 | }; |
@@ -137,6 +164,21 @@ static struct clk usart5_clk = { | |||
137 | .pmc_mask = 1 << AT91SAM9260_ID_US5, | 164 | .pmc_mask = 1 << AT91SAM9260_ID_US5, |
138 | .type = CLK_TYPE_PERIPHERAL, | 165 | .type = CLK_TYPE_PERIPHERAL, |
139 | }; | 166 | }; |
167 | static struct clk tc3_clk = { | ||
168 | .name = "tc3_clk", | ||
169 | .pmc_mask = 1 << AT91SAM9260_ID_TC3, | ||
170 | .type = CLK_TYPE_PERIPHERAL, | ||
171 | }; | ||
172 | static struct clk tc4_clk = { | ||
173 | .name = "tc4_clk", | ||
174 | .pmc_mask = 1 << AT91SAM9260_ID_TC4, | ||
175 | .type = CLK_TYPE_PERIPHERAL, | ||
176 | }; | ||
177 | static struct clk tc5_clk = { | ||
178 | .name = "tc5_clk", | ||
179 | .pmc_mask = 1 << AT91SAM9260_ID_TC5, | ||
180 | .type = CLK_TYPE_PERIPHERAL, | ||
181 | }; | ||
140 | 182 | ||
141 | static struct clk *periph_clocks[] __initdata = { | 183 | static struct clk *periph_clocks[] __initdata = { |
142 | &pioA_clk, | 184 | &pioA_clk, |
@@ -152,14 +194,18 @@ static struct clk *periph_clocks[] __initdata = { | |||
152 | &spi0_clk, | 194 | &spi0_clk, |
153 | &spi1_clk, | 195 | &spi1_clk, |
154 | // ssc | 196 | // ssc |
155 | // tc0 .. tc2 | 197 | &tc0_clk, |
198 | &tc1_clk, | ||
199 | &tc2_clk, | ||
156 | &ohci_clk, | 200 | &ohci_clk, |
157 | ðer_clk, | 201 | &macb_clk, |
158 | &isi_clk, | 202 | &isi_clk, |
159 | &usart3_clk, | 203 | &usart3_clk, |
160 | &usart4_clk, | 204 | &usart4_clk, |
161 | &usart5_clk, | 205 | &usart5_clk, |
162 | // tc3 .. tc5 | 206 | &tc3_clk, |
207 | &tc4_clk, | ||
208 | &tc5_clk, | ||
163 | // irq0 .. irq2 | 209 | // irq0 .. irq2 |
164 | }; | 210 | }; |
165 | 211 | ||
@@ -213,7 +259,7 @@ static struct at91_gpio_bank at91sam9260_gpio[] = { | |||
213 | 259 | ||
214 | static void at91sam9260_reset(void) | 260 | static void at91sam9260_reset(void) |
215 | { | 261 | { |
216 | at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); | 262 | at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); |
217 | } | 263 | } |
218 | 264 | ||
219 | 265 | ||
@@ -221,11 +267,37 @@ static void at91sam9260_reset(void) | |||
221 | * AT91SAM9260 processor initialization | 267 | * AT91SAM9260 processor initialization |
222 | * -------------------------------------------------------------------- */ | 268 | * -------------------------------------------------------------------- */ |
223 | 269 | ||
270 | static void __init at91sam9xe_initialize(void) | ||
271 | { | ||
272 | unsigned long cidr, sram_size; | ||
273 | |||
274 | cidr = at91_sys_read(AT91_DBGU_CIDR); | ||
275 | |||
276 | switch (cidr & AT91_CIDR_SRAMSIZ) { | ||
277 | case AT91_CIDR_SRAMSIZ_32K: | ||
278 | sram_size = 2 * SZ_16K; | ||
279 | break; | ||
280 | case AT91_CIDR_SRAMSIZ_16K: | ||
281 | default: | ||
282 | sram_size = SZ_16K; | ||
283 | } | ||
284 | |||
285 | at91sam9xe_sram_desc->virtual = AT91_IO_VIRT_BASE - sram_size; | ||
286 | at91sam9xe_sram_desc->length = sram_size; | ||
287 | |||
288 | iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc)); | ||
289 | } | ||
290 | |||
224 | void __init at91sam9260_initialize(unsigned long main_clock) | 291 | void __init at91sam9260_initialize(unsigned long main_clock) |
225 | { | 292 | { |
226 | /* Map peripherals */ | 293 | /* Map peripherals */ |
227 | iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); | 294 | iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); |
228 | 295 | ||
296 | if (cpu_is_at91sam9xe()) | ||
297 | at91sam9xe_initialize(); | ||
298 | else | ||
299 | iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc)); | ||
300 | |||
229 | at91_arch_reset = at91sam9260_reset; | 301 | at91_arch_reset = at91sam9260_reset; |
230 | at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) | 302 | at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) |
231 | | (1 << AT91SAM9260_ID_IRQ2); | 303 | | (1 << AT91SAM9260_ID_IRQ2); |
diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index f42d3a40ec3c..f7d342ccbebf 100644 --- a/arch/arm/mach-at91rm9200/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-at91rm9200/at91sam9260_devices.c | 2 | * arch/arm/mach-at91/at91sam9260_devices.c |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Atmel | 4 | * Copyright (C) 2006 Atmel |
5 | * | 5 | * |
@@ -128,7 +128,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} | |||
128 | 128 | ||
129 | #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) | 129 | #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) |
130 | static u64 eth_dmamask = 0xffffffffUL; | 130 | static u64 eth_dmamask = 0xffffffffUL; |
131 | static struct eth_platform_data eth_data; | 131 | static struct at91_eth_data eth_data; |
132 | 132 | ||
133 | static struct resource eth_resources[] = { | 133 | static struct resource eth_resources[] = { |
134 | [0] = { | 134 | [0] = { |
@@ -155,7 +155,7 @@ static struct platform_device at91sam9260_eth_device = { | |||
155 | .num_resources = ARRAY_SIZE(eth_resources), | 155 | .num_resources = ARRAY_SIZE(eth_resources), |
156 | }; | 156 | }; |
157 | 157 | ||
158 | void __init at91_add_device_eth(struct eth_platform_data *data) | 158 | void __init at91_add_device_eth(struct at91_eth_data *data) |
159 | { | 159 | { |
160 | if (!data) | 160 | if (!data) |
161 | return; | 161 | return; |
@@ -192,7 +192,7 @@ void __init at91_add_device_eth(struct eth_platform_data *data) | |||
192 | platform_device_register(&at91sam9260_eth_device); | 192 | platform_device_register(&at91sam9260_eth_device); |
193 | } | 193 | } |
194 | #else | 194 | #else |
195 | void __init at91_add_device_eth(struct eth_platform_data *data) {} | 195 | void __init at91_add_device_eth(struct at91_eth_data *data) {} |
196 | #endif | 196 | #endif |
197 | 197 | ||
198 | 198 | ||
@@ -229,7 +229,7 @@ static struct platform_device at91sam9260_mmc_device = { | |||
229 | .num_resources = ARRAY_SIZE(mmc_resources), | 229 | .num_resources = ARRAY_SIZE(mmc_resources), |
230 | }; | 230 | }; |
231 | 231 | ||
232 | void __init at91_add_device_mmc(struct at91_mmc_data *data) | 232 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) |
233 | { | 233 | { |
234 | if (!data) | 234 | if (!data) |
235 | return; | 235 | return; |
@@ -275,7 +275,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) | |||
275 | platform_device_register(&at91sam9260_mmc_device); | 275 | platform_device_register(&at91sam9260_mmc_device); |
276 | } | 276 | } |
277 | #else | 277 | #else |
278 | void __init at91_add_device_mmc(struct at91_mmc_data *data) {} | 278 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} |
279 | #endif | 279 | #endif |
280 | 280 | ||
281 | 281 | ||
@@ -515,6 +515,10 @@ u8 at91_leds_timer; | |||
515 | 515 | ||
516 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) | 516 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) |
517 | { | 517 | { |
518 | /* Enable GPIO to access the LEDs */ | ||
519 | at91_set_gpio_output(cpu_led, 1); | ||
520 | at91_set_gpio_output(timer_led, 1); | ||
521 | |||
518 | at91_leds_cpu = cpu_led; | 522 | at91_leds_cpu = cpu_led; |
519 | at91_leds_timer = timer_led; | 523 | at91_leds_timer = timer_led; |
520 | } | 524 | } |
diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index d242bb885c6d..784d1e682d6d 100644 --- a/arch/arm/mach-at91rm9200/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-at91rm9200/at91sam9261.c | 2 | * arch/arm/mach-at91/at91sam9261.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * | 5 | * |
@@ -97,6 +97,21 @@ static struct clk spi1_clk = { | |||
97 | .pmc_mask = 1 << AT91SAM9261_ID_SPI1, | 97 | .pmc_mask = 1 << AT91SAM9261_ID_SPI1, |
98 | .type = CLK_TYPE_PERIPHERAL, | 98 | .type = CLK_TYPE_PERIPHERAL, |
99 | }; | 99 | }; |
100 | static struct clk tc0_clk = { | ||
101 | .name = "tc0_clk", | ||
102 | .pmc_mask = 1 << AT91SAM9261_ID_TC0, | ||
103 | .type = CLK_TYPE_PERIPHERAL, | ||
104 | }; | ||
105 | static struct clk tc1_clk = { | ||
106 | .name = "tc1_clk", | ||
107 | .pmc_mask = 1 << AT91SAM9261_ID_TC1, | ||
108 | .type = CLK_TYPE_PERIPHERAL, | ||
109 | }; | ||
110 | static struct clk tc2_clk = { | ||
111 | .name = "tc2_clk", | ||
112 | .pmc_mask = 1 << AT91SAM9261_ID_TC2, | ||
113 | .type = CLK_TYPE_PERIPHERAL, | ||
114 | }; | ||
100 | static struct clk ohci_clk = { | 115 | static struct clk ohci_clk = { |
101 | .name = "ohci_clk", | 116 | .name = "ohci_clk", |
102 | .pmc_mask = 1 << AT91SAM9261_ID_UHP, | 117 | .pmc_mask = 1 << AT91SAM9261_ID_UHP, |
@@ -121,7 +136,9 @@ static struct clk *periph_clocks[] __initdata = { | |||
121 | &spi0_clk, | 136 | &spi0_clk, |
122 | &spi1_clk, | 137 | &spi1_clk, |
123 | // ssc 0 .. ssc2 | 138 | // ssc 0 .. ssc2 |
124 | // tc0 .. tc2 | 139 | &tc0_clk, |
140 | &tc1_clk, | ||
141 | &tc2_clk, | ||
125 | &ohci_clk, | 142 | &ohci_clk, |
126 | &lcdc_clk, | 143 | &lcdc_clk, |
127 | // irq0 .. irq2 | 144 | // irq0 .. irq2 |
@@ -208,7 +225,7 @@ static struct at91_gpio_bank at91sam9261_gpio[] = { | |||
208 | 225 | ||
209 | static void at91sam9261_reset(void) | 226 | static void at91sam9261_reset(void) |
210 | { | 227 | { |
211 | at91_sys_write(AT91_RSTC_CR, (0xA5 << 24) | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); | 228 | at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); |
212 | } | 229 | } |
213 | 230 | ||
214 | 231 | ||
diff --git a/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index ed1d79081b35..e1504766fd64 100644 --- a/arch/arm/mach-at91rm9200/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-at91rm9200/at91sam9261_devices.c | 2 | * arch/arm/mach-at91/at91sam9261_devices.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> | 4 | * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> |
5 | * Copyright (C) 2005 David Brownell | 5 | * Copyright (C) 2005 David Brownell |
@@ -159,7 +159,7 @@ static struct platform_device at91sam9261_mmc_device = { | |||
159 | .num_resources = ARRAY_SIZE(mmc_resources), | 159 | .num_resources = ARRAY_SIZE(mmc_resources), |
160 | }; | 160 | }; |
161 | 161 | ||
162 | void __init at91_add_device_mmc(struct at91_mmc_data *data) | 162 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) |
163 | { | 163 | { |
164 | if (!data) | 164 | if (!data) |
165 | return; | 165 | return; |
@@ -192,7 +192,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) | |||
192 | platform_device_register(&at91sam9261_mmc_device); | 192 | platform_device_register(&at91sam9261_mmc_device); |
193 | } | 193 | } |
194 | #else | 194 | #else |
195 | void __init at91_add_device_mmc(struct at91_mmc_data *data) {} | 195 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} |
196 | #endif | 196 | #endif |
197 | 197 | ||
198 | 198 | ||
@@ -513,6 +513,10 @@ u8 at91_leds_timer; | |||
513 | 513 | ||
514 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) | 514 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) |
515 | { | 515 | { |
516 | /* Enable GPIO to access the LEDs */ | ||
517 | at91_set_gpio_output(cpu_led, 1); | ||
518 | at91_set_gpio_output(timer_led, 1); | ||
519 | |||
516 | at91_leds_cpu = cpu_led; | 520 | at91_leds_cpu = cpu_led; |
517 | at91_leds_timer = timer_led; | 521 | at91_leds_timer = timer_led; |
518 | } | 522 | } |
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c new file mode 100644 index 000000000000..6aa342e8f1b1 --- /dev/null +++ b/arch/arm/mach-at91/at91sam9263.c | |||
@@ -0,0 +1,313 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-at91/at91sam9263.c | ||
3 | * | ||
4 | * Copyright (C) 2007 Atmel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | |||
15 | #include <asm/mach/arch.h> | ||
16 | #include <asm/mach/map.h> | ||
17 | #include <asm/arch/at91sam9263.h> | ||
18 | #include <asm/arch/at91_pmc.h> | ||
19 | #include <asm/arch/at91_rstc.h> | ||
20 | |||
21 | #include "generic.h" | ||
22 | #include "clock.h" | ||
23 | |||
24 | static struct map_desc at91sam9263_io_desc[] __initdata = { | ||
25 | { | ||
26 | .virtual = AT91_VA_BASE_SYS, | ||
27 | .pfn = __phys_to_pfn(AT91_BASE_SYS), | ||
28 | .length = SZ_16K, | ||
29 | .type = MT_DEVICE, | ||
30 | }, { | ||
31 | .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE, | ||
32 | .pfn = __phys_to_pfn(AT91SAM9263_SRAM0_BASE), | ||
33 | .length = AT91SAM9263_SRAM0_SIZE, | ||
34 | .type = MT_DEVICE, | ||
35 | }, { | ||
36 | .virtual = AT91_IO_VIRT_BASE - AT91SAM9263_SRAM0_SIZE - AT91SAM9263_SRAM1_SIZE, | ||
37 | .pfn = __phys_to_pfn(AT91SAM9263_SRAM1_BASE), | ||
38 | .length = AT91SAM9263_SRAM1_SIZE, | ||
39 | .type = MT_DEVICE, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | /* -------------------------------------------------------------------- | ||
44 | * Clocks | ||
45 | * -------------------------------------------------------------------- */ | ||
46 | |||
47 | /* | ||
48 | * The peripheral clocks. | ||
49 | */ | ||
50 | static struct clk pioA_clk = { | ||
51 | .name = "pioA_clk", | ||
52 | .pmc_mask = 1 << AT91SAM9263_ID_PIOA, | ||
53 | .type = CLK_TYPE_PERIPHERAL, | ||
54 | }; | ||
55 | static struct clk pioB_clk = { | ||
56 | .name = "pioB_clk", | ||
57 | .pmc_mask = 1 << AT91SAM9263_ID_PIOB, | ||
58 | .type = CLK_TYPE_PERIPHERAL, | ||
59 | }; | ||
60 | static struct clk pioCDE_clk = { | ||
61 | .name = "pioCDE_clk", | ||
62 | .pmc_mask = 1 << AT91SAM9263_ID_PIOCDE, | ||
63 | .type = CLK_TYPE_PERIPHERAL, | ||
64 | }; | ||
65 | static struct clk usart0_clk = { | ||
66 | .name = "usart0_clk", | ||
67 | .pmc_mask = 1 << AT91SAM9263_ID_US0, | ||
68 | .type = CLK_TYPE_PERIPHERAL, | ||
69 | }; | ||
70 | static struct clk usart1_clk = { | ||
71 | .name = "usart1_clk", | ||
72 | .pmc_mask = 1 << AT91SAM9263_ID_US1, | ||
73 | .type = CLK_TYPE_PERIPHERAL, | ||
74 | }; | ||
75 | static struct clk usart2_clk = { | ||
76 | .name = "usart2_clk", | ||
77 | .pmc_mask = 1 << AT91SAM9263_ID_US2, | ||
78 | .type = CLK_TYPE_PERIPHERAL, | ||
79 | }; | ||
80 | static struct clk mmc0_clk = { | ||
81 | .name = "mci0_clk", | ||
82 | .pmc_mask = 1 << AT91SAM9263_ID_MCI0, | ||
83 | .type = CLK_TYPE_PERIPHERAL, | ||
84 | }; | ||
85 | static struct clk mmc1_clk = { | ||
86 | .name = "mci1_clk", | ||
87 | .pmc_mask = 1 << AT91SAM9263_ID_MCI1, | ||
88 | .type = CLK_TYPE_PERIPHERAL, | ||
89 | }; | ||
90 | static struct clk twi_clk = { | ||
91 | .name = "twi_clk", | ||
92 | .pmc_mask = 1 << AT91SAM9263_ID_TWI, | ||
93 | .type = CLK_TYPE_PERIPHERAL, | ||
94 | }; | ||
95 | static struct clk spi0_clk = { | ||
96 | .name = "spi0_clk", | ||
97 | .pmc_mask = 1 << AT91SAM9263_ID_SPI0, | ||
98 | .type = CLK_TYPE_PERIPHERAL, | ||
99 | }; | ||
100 | static struct clk spi1_clk = { | ||
101 | .name = "spi1_clk", | ||
102 | .pmc_mask = 1 << AT91SAM9263_ID_SPI1, | ||
103 | .type = CLK_TYPE_PERIPHERAL, | ||
104 | }; | ||
105 | static struct clk tcb_clk = { | ||
106 | .name = "tcb_clk", | ||
107 | .pmc_mask = 1 << AT91SAM9263_ID_TCB, | ||
108 | .type = CLK_TYPE_PERIPHERAL, | ||
109 | }; | ||
110 | static struct clk macb_clk = { | ||
111 | .name = "macb_clk", | ||
112 | .pmc_mask = 1 << AT91SAM9263_ID_EMAC, | ||
113 | .type = CLK_TYPE_PERIPHERAL, | ||
114 | }; | ||
115 | static struct clk udc_clk = { | ||
116 | .name = "udc_clk", | ||
117 | .pmc_mask = 1 << AT91SAM9263_ID_UDP, | ||
118 | .type = CLK_TYPE_PERIPHERAL, | ||
119 | }; | ||
120 | static struct clk isi_clk = { | ||
121 | .name = "isi_clk", | ||
122 | .pmc_mask = 1 << AT91SAM9263_ID_ISI, | ||
123 | .type = CLK_TYPE_PERIPHERAL, | ||
124 | }; | ||
125 | static struct clk lcdc_clk = { | ||
126 | .name = "lcdc_clk", | ||
127 | .pmc_mask = 1 << AT91SAM9263_ID_ISI, | ||
128 | .type = CLK_TYPE_PERIPHERAL, | ||
129 | }; | ||
130 | static struct clk ohci_clk = { | ||
131 | .name = "ohci_clk", | ||
132 | .pmc_mask = 1 << AT91SAM9263_ID_UHP, | ||
133 | .type = CLK_TYPE_PERIPHERAL, | ||
134 | }; | ||
135 | |||
136 | static struct clk *periph_clocks[] __initdata = { | ||
137 | &pioA_clk, | ||
138 | &pioB_clk, | ||
139 | &pioCDE_clk, | ||
140 | &usart0_clk, | ||
141 | &usart1_clk, | ||
142 | &usart2_clk, | ||
143 | &mmc0_clk, | ||
144 | &mmc1_clk, | ||
145 | // can | ||
146 | &twi_clk, | ||
147 | &spi0_clk, | ||
148 | &spi1_clk, | ||
149 | // ssc0 .. ssc1 | ||
150 | // ac97 | ||
151 | &tcb_clk, | ||
152 | // pwmc | ||
153 | &macb_clk, | ||
154 | // 2dge | ||
155 | &udc_clk, | ||
156 | &isi_clk, | ||
157 | &lcdc_clk, | ||
158 | // dma | ||
159 | &ohci_clk, | ||
160 | // irq0 .. irq1 | ||
161 | }; | ||
162 | |||
163 | /* | ||
164 | * The four programmable clocks. | ||
165 | * You must configure pin multiplexing to bring these signals out. | ||
166 | */ | ||
167 | static struct clk pck0 = { | ||
168 | .name = "pck0", | ||
169 | .pmc_mask = AT91_PMC_PCK0, | ||
170 | .type = CLK_TYPE_PROGRAMMABLE, | ||
171 | .id = 0, | ||
172 | }; | ||
173 | static struct clk pck1 = { | ||
174 | .name = "pck1", | ||
175 | .pmc_mask = AT91_PMC_PCK1, | ||
176 | .type = CLK_TYPE_PROGRAMMABLE, | ||
177 | .id = 1, | ||
178 | }; | ||
179 | static struct clk pck2 = { | ||
180 | .name = "pck2", | ||
181 | .pmc_mask = AT91_PMC_PCK2, | ||
182 | .type = CLK_TYPE_PROGRAMMABLE, | ||
183 | .id = 2, | ||
184 | }; | ||
185 | static struct clk pck3 = { | ||
186 | .name = "pck3", | ||
187 | .pmc_mask = AT91_PMC_PCK3, | ||
188 | .type = CLK_TYPE_PROGRAMMABLE, | ||
189 | .id = 3, | ||
190 | }; | ||
191 | |||
192 | static void __init at91sam9263_register_clocks(void) | ||
193 | { | ||
194 | int i; | ||
195 | |||
196 | for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) | ||
197 | clk_register(periph_clocks[i]); | ||
198 | |||
199 | clk_register(&pck0); | ||
200 | clk_register(&pck1); | ||
201 | clk_register(&pck2); | ||
202 | clk_register(&pck3); | ||
203 | } | ||
204 | |||
205 | /* -------------------------------------------------------------------- | ||
206 | * GPIO | ||
207 | * -------------------------------------------------------------------- */ | ||
208 | |||
209 | static struct at91_gpio_bank at91sam9263_gpio[] = { | ||
210 | { | ||
211 | .id = AT91SAM9263_ID_PIOA, | ||
212 | .offset = AT91_PIOA, | ||
213 | .clock = &pioA_clk, | ||
214 | }, { | ||
215 | .id = AT91SAM9263_ID_PIOB, | ||
216 | .offset = AT91_PIOB, | ||
217 | .clock = &pioB_clk, | ||
218 | }, { | ||
219 | .id = AT91SAM9263_ID_PIOCDE, | ||
220 | .offset = AT91_PIOC, | ||
221 | .clock = &pioCDE_clk, | ||
222 | }, { | ||
223 | .id = AT91SAM9263_ID_PIOCDE, | ||
224 | .offset = AT91_PIOD, | ||
225 | .clock = &pioCDE_clk, | ||
226 | }, { | ||
227 | .id = AT91SAM9263_ID_PIOCDE, | ||
228 | .offset = AT91_PIOE, | ||
229 | .clock = &pioCDE_clk, | ||
230 | } | ||
231 | }; | ||
232 | |||
233 | static void at91sam9263_reset(void) | ||
234 | { | ||
235 | at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST); | ||
236 | } | ||
237 | |||
238 | |||
239 | /* -------------------------------------------------------------------- | ||
240 | * AT91SAM9263 processor initialization | ||
241 | * -------------------------------------------------------------------- */ | ||
242 | |||
243 | void __init at91sam9263_initialize(unsigned long main_clock) | ||
244 | { | ||
245 | /* Map peripherals */ | ||
246 | iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc)); | ||
247 | |||
248 | at91_arch_reset = at91sam9263_reset; | ||
249 | at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1); | ||
250 | |||
251 | /* Init clock subsystem */ | ||
252 | at91_clock_init(main_clock); | ||
253 | |||
254 | /* Register the processor-specific clocks */ | ||
255 | at91sam9263_register_clocks(); | ||
256 | |||
257 | /* Register GPIO subsystem */ | ||
258 | at91_gpio_init(at91sam9263_gpio, 5); | ||
259 | } | ||
260 | |||
261 | /* -------------------------------------------------------------------- | ||
262 | * Interrupt initialization | ||
263 | * -------------------------------------------------------------------- */ | ||
264 | |||
265 | /* | ||
266 | * The default interrupt priority levels (0 = lowest, 7 = highest). | ||
267 | */ | ||
268 | static unsigned int at91sam9263_default_irq_priority[NR_AIC_IRQS] __initdata = { | ||
269 | 7, /* Advanced Interrupt Controller (FIQ) */ | ||
270 | 7, /* System Peripherals */ | ||
271 | 0, /* Parallel IO Controller A */ | ||
272 | 0, /* Parallel IO Controller B */ | ||
273 | 0, /* Parallel IO Controller C, D and E */ | ||
274 | 0, | ||
275 | 0, | ||
276 | 6, /* USART 0 */ | ||
277 | 6, /* USART 1 */ | ||
278 | 6, /* USART 2 */ | ||
279 | 0, /* Multimedia Card Interface 0 */ | ||
280 | 0, /* Multimedia Card Interface 1 */ | ||
281 | 4, /* CAN */ | ||
282 | 0, /* Two-Wire Interface */ | ||
283 | 6, /* Serial Peripheral Interface 0 */ | ||
284 | 6, /* Serial Peripheral Interface 1 */ | ||
285 | 5, /* Serial Synchronous Controller 0 */ | ||
286 | 5, /* Serial Synchronous Controller 1 */ | ||
287 | 6, /* AC97 Controller */ | ||
288 | 0, /* Timer Counter 0, 1 and 2 */ | ||
289 | 0, /* Pulse Width Modulation Controller */ | ||
290 | 3, /* Ethernet */ | ||
291 | 0, | ||
292 | 0, /* 2D Graphic Engine */ | ||
293 | 3, /* USB Device Port */ | ||
294 | 0, /* Image Sensor Interface */ | ||
295 | 3, /* LDC Controller */ | ||
296 | 0, /* DMA Controller */ | ||
297 | 0, | ||
298 | 3, /* USB Host port */ | ||
299 | 0, /* Advanced Interrupt Controller (IRQ0) */ | ||
300 | 0, /* Advanced Interrupt Controller (IRQ1) */ | ||
301 | }; | ||
302 | |||
303 | void __init at91sam9263_init_interrupts(unsigned int priority[NR_AIC_IRQS]) | ||
304 | { | ||
305 | if (!priority) | ||
306 | priority = at91sam9263_default_irq_priority; | ||
307 | |||
308 | /* Initialize the AIC interrupt controller */ | ||
309 | at91_aic_init(priority); | ||
310 | |||
311 | /* Enable GPIO interrupts */ | ||
312 | at91_gpio_irq_setup(); | ||
313 | } | ||
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c new file mode 100644 index 000000000000..d9af7ca58bce --- /dev/null +++ b/arch/arm/mach-at91/at91sam9263_devices.c | |||
@@ -0,0 +1,818 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-at91/at91sam9263_devices.c | ||
3 | * | ||
4 | * Copyright (C) 2007 Atmel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | #include <asm/mach/arch.h> | ||
13 | #include <asm/mach/map.h> | ||
14 | |||
15 | #include <linux/platform_device.h> | ||
16 | |||
17 | #include <asm/arch/board.h> | ||
18 | #include <asm/arch/gpio.h> | ||
19 | #include <asm/arch/at91sam9263.h> | ||
20 | #include <asm/arch/at91sam926x_mc.h> | ||
21 | #include <asm/arch/at91sam9263_matrix.h> | ||
22 | |||
23 | #include "generic.h" | ||
24 | |||
25 | #define SZ_512 0x00000200 | ||
26 | #define SZ_256 0x00000100 | ||
27 | #define SZ_16 0x00000010 | ||
28 | |||
29 | /* -------------------------------------------------------------------- | ||
30 | * USB Host | ||
31 | * -------------------------------------------------------------------- */ | ||
32 | |||
33 | #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) | ||
34 | static u64 ohci_dmamask = 0xffffffffUL; | ||
35 | static struct at91_usbh_data usbh_data; | ||
36 | |||
37 | static struct resource usbh_resources[] = { | ||
38 | [0] = { | ||
39 | .start = AT91SAM9263_UHP_BASE, | ||
40 | .end = AT91SAM9263_UHP_BASE + SZ_1M - 1, | ||
41 | .flags = IORESOURCE_MEM, | ||
42 | }, | ||
43 | [1] = { | ||
44 | .start = AT91SAM9263_ID_UHP, | ||
45 | .end = AT91SAM9263_ID_UHP, | ||
46 | .flags = IORESOURCE_IRQ, | ||
47 | }, | ||
48 | }; | ||
49 | |||
50 | static struct platform_device at91_usbh_device = { | ||
51 | .name = "at91_ohci", | ||
52 | .id = -1, | ||
53 | .dev = { | ||
54 | .dma_mask = &ohci_dmamask, | ||
55 | .coherent_dma_mask = 0xffffffff, | ||
56 | .platform_data = &usbh_data, | ||
57 | }, | ||
58 | .resource = usbh_resources, | ||
59 | .num_resources = ARRAY_SIZE(usbh_resources), | ||
60 | }; | ||
61 | |||
62 | void __init at91_add_device_usbh(struct at91_usbh_data *data) | ||
63 | { | ||
64 | int i; | ||
65 | |||
66 | if (!data) | ||
67 | return; | ||
68 | |||
69 | /* Enable VBus control for UHP ports */ | ||
70 | for (i = 0; i < data->ports; i++) { | ||
71 | if (data->vbus_pin[i]) | ||
72 | at91_set_gpio_output(data->vbus_pin[i], 0); | ||
73 | } | ||
74 | |||
75 | usbh_data = *data; | ||
76 | platform_device_register(&at91_usbh_device); | ||
77 | } | ||
78 | #else | ||
79 | void __init at91_add_device_usbh(struct at91_usbh_data *data) {} | ||
80 | #endif | ||
81 | |||
82 | |||
83 | /* -------------------------------------------------------------------- | ||
84 | * USB Device (Gadget) | ||
85 | * -------------------------------------------------------------------- */ | ||
86 | |||
87 | #ifdef CONFIG_USB_GADGET_AT91 | ||
88 | static struct at91_udc_data udc_data; | ||
89 | |||
90 | static struct resource udc_resources[] = { | ||
91 | [0] = { | ||
92 | .start = AT91SAM9263_BASE_UDP, | ||
93 | .end = AT91SAM9263_BASE_UDP + SZ_16K - 1, | ||
94 | .flags = IORESOURCE_MEM, | ||
95 | }, | ||
96 | [1] = { | ||
97 | .start = AT91SAM9263_ID_UDP, | ||
98 | .end = AT91SAM9263_ID_UDP, | ||
99 | .flags = IORESOURCE_IRQ, | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | static struct platform_device at91_udc_device = { | ||
104 | .name = "at91_udc", | ||
105 | .id = -1, | ||
106 | .dev = { | ||
107 | .platform_data = &udc_data, | ||
108 | }, | ||
109 | .resource = udc_resources, | ||
110 | .num_resources = ARRAY_SIZE(udc_resources), | ||
111 | }; | ||
112 | |||
113 | void __init at91_add_device_udc(struct at91_udc_data *data) | ||
114 | { | ||
115 | if (!data) | ||
116 | return; | ||
117 | |||
118 | if (data->vbus_pin) { | ||
119 | at91_set_gpio_input(data->vbus_pin, 0); | ||
120 | at91_set_deglitch(data->vbus_pin, 1); | ||
121 | } | ||
122 | |||
123 | /* Pullup pin is handled internally by USB device peripheral */ | ||
124 | |||
125 | udc_data = *data; | ||
126 | platform_device_register(&at91_udc_device); | ||
127 | } | ||
128 | #else | ||
129 | void __init at91_add_device_udc(struct at91_udc_data *data) {} | ||
130 | #endif | ||
131 | |||
132 | |||
133 | /* -------------------------------------------------------------------- | ||
134 | * Ethernet | ||
135 | * -------------------------------------------------------------------- */ | ||
136 | |||
137 | #if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) | ||
138 | static u64 eth_dmamask = 0xffffffffUL; | ||
139 | static struct at91_eth_data eth_data; | ||
140 | |||
141 | static struct resource eth_resources[] = { | ||
142 | [0] = { | ||
143 | .start = AT91SAM9263_BASE_EMAC, | ||
144 | .end = AT91SAM9263_BASE_EMAC + SZ_16K - 1, | ||
145 | .flags = IORESOURCE_MEM, | ||
146 | }, | ||
147 | [1] = { | ||
148 | .start = AT91SAM9263_ID_EMAC, | ||
149 | .end = AT91SAM9263_ID_EMAC, | ||
150 | .flags = IORESOURCE_IRQ, | ||
151 | }, | ||
152 | }; | ||
153 | |||
154 | static struct platform_device at91sam9263_eth_device = { | ||
155 | .name = "macb", | ||
156 | .id = -1, | ||
157 | .dev = { | ||
158 | .dma_mask = ð_dmamask, | ||
159 | .coherent_dma_mask = 0xffffffff, | ||
160 | .platform_data = ð_data, | ||
161 | }, | ||
162 | .resource = eth_resources, | ||
163 | .num_resources = ARRAY_SIZE(eth_resources), | ||
164 | }; | ||
165 | |||
166 | void __init at91_add_device_eth(struct at91_eth_data *data) | ||
167 | { | ||
168 | if (!data) | ||
169 | return; | ||
170 | |||
171 | if (data->phy_irq_pin) { | ||
172 | at91_set_gpio_input(data->phy_irq_pin, 0); | ||
173 | at91_set_deglitch(data->phy_irq_pin, 1); | ||
174 | } | ||
175 | |||
176 | /* Pins used for MII and RMII */ | ||
177 | at91_set_A_periph(AT91_PIN_PE21, 0); /* ETXCK_EREFCK */ | ||
178 | at91_set_B_periph(AT91_PIN_PC25, 0); /* ERXDV */ | ||
179 | at91_set_A_periph(AT91_PIN_PE25, 0); /* ERX0 */ | ||
180 | at91_set_A_periph(AT91_PIN_PE26, 0); /* ERX1 */ | ||
181 | at91_set_A_periph(AT91_PIN_PE27, 0); /* ERXER */ | ||
182 | at91_set_A_periph(AT91_PIN_PE28, 0); /* ETXEN */ | ||
183 | at91_set_A_periph(AT91_PIN_PE23, 0); /* ETX0 */ | ||
184 | at91_set_A_periph(AT91_PIN_PE24, 0); /* ETX1 */ | ||
185 | at91_set_A_periph(AT91_PIN_PE30, 0); /* EMDIO */ | ||
186 | at91_set_A_periph(AT91_PIN_PE29, 0); /* EMDC */ | ||
187 | |||
188 | if (!data->is_rmii) { | ||
189 | at91_set_A_periph(AT91_PIN_PE22, 0); /* ECRS */ | ||
190 | at91_set_B_periph(AT91_PIN_PC26, 0); /* ECOL */ | ||
191 | at91_set_B_periph(AT91_PIN_PC22, 0); /* ERX2 */ | ||
192 | at91_set_B_periph(AT91_PIN_PC23, 0); /* ERX3 */ | ||
193 | at91_set_B_periph(AT91_PIN_PC27, 0); /* ERXCK */ | ||
194 | at91_set_B_periph(AT91_PIN_PC20, 0); /* ETX2 */ | ||
195 | at91_set_B_periph(AT91_PIN_PC21, 0); /* ETX3 */ | ||
196 | at91_set_B_periph(AT91_PIN_PC24, 0); /* ETXER */ | ||
197 | } | ||
198 | |||
199 | eth_data = *data; | ||
200 | platform_device_register(&at91sam9263_eth_device); | ||
201 | } | ||
202 | #else | ||
203 | void __init at91_add_device_eth(struct at91_eth_data *data) {} | ||
204 | #endif | ||
205 | |||
206 | |||
207 | /* -------------------------------------------------------------------- | ||
208 | * MMC / SD | ||
209 | * -------------------------------------------------------------------- */ | ||
210 | |||
211 | #if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) | ||
212 | static u64 mmc_dmamask = 0xffffffffUL; | ||
213 | static struct at91_mmc_data mmc0_data, mmc1_data; | ||
214 | |||
215 | static struct resource mmc0_resources[] = { | ||
216 | [0] = { | ||
217 | .start = AT91SAM9263_BASE_MCI0, | ||
218 | .end = AT91SAM9263_BASE_MCI0 + SZ_16K - 1, | ||
219 | .flags = IORESOURCE_MEM, | ||
220 | }, | ||
221 | [1] = { | ||
222 | .start = AT91SAM9263_ID_MCI0, | ||
223 | .end = AT91SAM9263_ID_MCI0, | ||
224 | .flags = IORESOURCE_IRQ, | ||
225 | }, | ||
226 | }; | ||
227 | |||
228 | static struct platform_device at91sam9263_mmc0_device = { | ||
229 | .name = "at91_mci", | ||
230 | .id = 0, | ||
231 | .dev = { | ||
232 | .dma_mask = &mmc_dmamask, | ||
233 | .coherent_dma_mask = 0xffffffff, | ||
234 | .platform_data = &mmc0_data, | ||
235 | }, | ||
236 | .resource = mmc0_resources, | ||
237 | .num_resources = ARRAY_SIZE(mmc0_resources), | ||
238 | }; | ||
239 | |||
240 | static struct resource mmc1_resources[] = { | ||
241 | [0] = { | ||
242 | .start = AT91SAM9263_BASE_MCI1, | ||
243 | .end = AT91SAM9263_BASE_MCI1 + SZ_16K - 1, | ||
244 | .flags = IORESOURCE_MEM, | ||
245 | }, | ||
246 | [1] = { | ||
247 | .start = AT91SAM9263_ID_MCI1, | ||
248 | .end = AT91SAM9263_ID_MCI1, | ||
249 | .flags = IORESOURCE_IRQ, | ||
250 | }, | ||
251 | }; | ||
252 | |||
253 | static struct platform_device at91sam9263_mmc1_device = { | ||
254 | .name = "at91_mci", | ||
255 | .id = 1, | ||
256 | .dev = { | ||
257 | .dma_mask = &mmc_dmamask, | ||
258 | .coherent_dma_mask = 0xffffffff, | ||
259 | .platform_data = &mmc1_data, | ||
260 | }, | ||
261 | .resource = mmc1_resources, | ||
262 | .num_resources = ARRAY_SIZE(mmc1_resources), | ||
263 | }; | ||
264 | |||
265 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) | ||
266 | { | ||
267 | if (!data) | ||
268 | return; | ||
269 | |||
270 | /* input/irq */ | ||
271 | if (data->det_pin) { | ||
272 | at91_set_gpio_input(data->det_pin, 1); | ||
273 | at91_set_deglitch(data->det_pin, 1); | ||
274 | } | ||
275 | if (data->wp_pin) | ||
276 | at91_set_gpio_input(data->wp_pin, 1); | ||
277 | if (data->vcc_pin) | ||
278 | at91_set_gpio_output(data->vcc_pin, 0); | ||
279 | |||
280 | if (mmc_id == 0) { /* MCI0 */ | ||
281 | /* CLK */ | ||
282 | at91_set_A_periph(AT91_PIN_PA12, 0); | ||
283 | |||
284 | if (data->slot_b) { | ||
285 | /* CMD */ | ||
286 | at91_set_A_periph(AT91_PIN_PA16, 1); | ||
287 | |||
288 | /* DAT0, maybe DAT1..DAT3 */ | ||
289 | at91_set_A_periph(AT91_PIN_PA17, 1); | ||
290 | if (data->wire4) { | ||
291 | at91_set_A_periph(AT91_PIN_PA18, 1); | ||
292 | at91_set_A_periph(AT91_PIN_PA19, 1); | ||
293 | at91_set_A_periph(AT91_PIN_PA20, 1); | ||
294 | } | ||
295 | } else { | ||
296 | /* CMD */ | ||
297 | at91_set_A_periph(AT91_PIN_PA1, 1); | ||
298 | |||
299 | /* DAT0, maybe DAT1..DAT3 */ | ||
300 | at91_set_A_periph(AT91_PIN_PA0, 1); | ||
301 | if (data->wire4) { | ||
302 | at91_set_A_periph(AT91_PIN_PA3, 1); | ||
303 | at91_set_A_periph(AT91_PIN_PA4, 1); | ||
304 | at91_set_A_periph(AT91_PIN_PA5, 1); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | mmc0_data = *data; | ||
309 | at91_clock_associate("mci0_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); | ||
310 | platform_device_register(&at91sam9263_mmc0_device); | ||
311 | } else { /* MCI1 */ | ||
312 | /* CLK */ | ||
313 | at91_set_A_periph(AT91_PIN_PA6, 0); | ||
314 | |||
315 | if (data->slot_b) { | ||
316 | /* CMD */ | ||
317 | at91_set_A_periph(AT91_PIN_PA21, 1); | ||
318 | |||
319 | /* DAT0, maybe DAT1..DAT3 */ | ||
320 | at91_set_A_periph(AT91_PIN_PA22, 1); | ||
321 | if (data->wire4) { | ||
322 | at91_set_A_periph(AT91_PIN_PA23, 1); | ||
323 | at91_set_A_periph(AT91_PIN_PA24, 1); | ||
324 | at91_set_A_periph(AT91_PIN_PA25, 1); | ||
325 | } | ||
326 | } else { | ||
327 | /* CMD */ | ||
328 | at91_set_A_periph(AT91_PIN_PA7, 1); | ||
329 | |||
330 | /* DAT0, maybe DAT1..DAT3 */ | ||
331 | at91_set_A_periph(AT91_PIN_PA8, 1); | ||
332 | if (data->wire4) { | ||
333 | at91_set_A_periph(AT91_PIN_PA9, 1); | ||
334 | at91_set_A_periph(AT91_PIN_PA10, 1); | ||
335 | at91_set_A_periph(AT91_PIN_PA11, 1); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | mmc1_data = *data; | ||
340 | at91_clock_associate("mci1_clk", &at91sam9263_mmc1_device.dev, "mci_clk"); | ||
341 | platform_device_register(&at91sam9263_mmc1_device); | ||
342 | } | ||
343 | } | ||
344 | #else | ||
345 | void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} | ||
346 | #endif | ||
347 | |||
348 | |||
349 | /* -------------------------------------------------------------------- | ||
350 | * NAND / SmartMedia | ||
351 | * -------------------------------------------------------------------- */ | ||
352 | |||
353 | #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) | ||
354 | static struct at91_nand_data nand_data; | ||
355 | |||
356 | #define NAND_BASE AT91_CHIPSELECT_3 | ||
357 | |||
358 | static struct resource nand_resources[] = { | ||
359 | { | ||
360 | .start = NAND_BASE, | ||
361 | .end = NAND_BASE + SZ_256M - 1, | ||
362 | .flags = IORESOURCE_MEM, | ||
363 | } | ||
364 | }; | ||
365 | |||
366 | static struct platform_device at91sam9263_nand_device = { | ||
367 | .name = "at91_nand", | ||
368 | .id = -1, | ||
369 | .dev = { | ||
370 | .platform_data = &nand_data, | ||
371 | }, | ||
372 | .resource = nand_resources, | ||
373 | .num_resources = ARRAY_SIZE(nand_resources), | ||
374 | }; | ||
375 | |||
376 | void __init at91_add_device_nand(struct at91_nand_data *data) | ||
377 | { | ||
378 | unsigned long csa, mode; | ||
379 | |||
380 | if (!data) | ||
381 | return; | ||
382 | |||
383 | csa = at91_sys_read(AT91_MATRIX_EBI0CSA); | ||
384 | at91_sys_write(AT91_MATRIX_EBI0CSA, csa | AT91_MATRIX_EBI0_CS3A_SMC); | ||
385 | |||
386 | /* set the bus interface characteristics */ | ||
387 | at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) | ||
388 | | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); | ||
389 | |||
390 | at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(3) | AT91_SMC_NCS_WRPULSE_(3) | ||
391 | | AT91_SMC_NRDPULSE_(3) | AT91_SMC_NCS_RDPULSE_(3)); | ||
392 | |||
393 | at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(5) | AT91_SMC_NRDCYCLE_(5)); | ||
394 | |||
395 | if (data->bus_width_16) | ||
396 | mode = AT91_SMC_DBW_16; | ||
397 | else | ||
398 | mode = AT91_SMC_DBW_8; | ||
399 | at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(2)); | ||
400 | |||
401 | /* enable pin */ | ||
402 | if (data->enable_pin) | ||
403 | at91_set_gpio_output(data->enable_pin, 1); | ||
404 | |||
405 | /* ready/busy pin */ | ||
406 | if (data->rdy_pin) | ||
407 | at91_set_gpio_input(data->rdy_pin, 1); | ||
408 | |||
409 | /* card detect pin */ | ||
410 | if (data->det_pin) | ||
411 | at91_set_gpio_input(data->det_pin, 1); | ||
412 | |||
413 | nand_data = *data; | ||
414 | platform_device_register(&at91sam9263_nand_device); | ||
415 | } | ||
416 | #else | ||
417 | void __init at91_add_device_nand(struct at91_nand_data *data) {} | ||
418 | #endif | ||
419 | |||
420 | |||
421 | /* -------------------------------------------------------------------- | ||
422 | * TWI (i2c) | ||
423 | * -------------------------------------------------------------------- */ | ||
424 | |||
425 | #if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) | ||
426 | |||
427 | static struct resource twi_resources[] = { | ||
428 | [0] = { | ||
429 | .start = AT91SAM9263_BASE_TWI, | ||
430 | .end = AT91SAM9263_BASE_TWI + SZ_16K - 1, | ||
431 | .flags = IORESOURCE_MEM, | ||
432 | }, | ||
433 | [1] = { | ||
434 | .start = AT91SAM9263_ID_TWI, | ||
435 | .end = AT91SAM9263_ID_TWI, | ||
436 | .flags = IORESOURCE_IRQ, | ||
437 | }, | ||
438 | }; | ||
439 | |||
440 | static struct platform_device at91sam9263_twi_device = { | ||
441 | .name = "at91_i2c", | ||
442 | .id = -1, | ||
443 | .resource = twi_resources, | ||
444 | .num_resources = ARRAY_SIZE(twi_resources), | ||
445 | }; | ||
446 | |||
447 | void __init at91_add_device_i2c(void) | ||
448 | { | ||
449 | /* pins used for TWI interface */ | ||
450 | at91_set_A_periph(AT91_PIN_PB4, 0); /* TWD */ | ||
451 | at91_set_multi_drive(AT91_PIN_PB4, 1); | ||
452 | |||
453 | at91_set_A_periph(AT91_PIN_PB5, 0); /* TWCK */ | ||
454 | at91_set_multi_drive(AT91_PIN_PB5, 1); | ||
455 | |||
456 | platform_device_register(&at91sam9263_twi_device); | ||
457 | } | ||
458 | #else | ||
459 | void __init at91_add_device_i2c(void) {} | ||
460 | #endif | ||
461 | |||
462 | |||
463 | /* -------------------------------------------------------------------- | ||
464 | * SPI | ||
465 | * -------------------------------------------------------------------- */ | ||
466 | |||
467 | #if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) | ||
468 | static u64 spi_dmamask = 0xffffffffUL; | ||
469 | |||
470 | static struct resource spi0_resources[] = { | ||
471 | [0] = { | ||
472 | .start = AT91SAM9263_BASE_SPI0, | ||
473 | .end = AT91SAM9263_BASE_SPI0 + SZ_16K - 1, | ||
474 | .flags = IORESOURCE_MEM, | ||
475 | }, | ||
476 | [1] = { | ||
477 | .start = AT91SAM9263_ID_SPI0, | ||
478 | .end = AT91SAM9263_ID_SPI0, | ||
479 | .flags = IORESOURCE_IRQ, | ||
480 | }, | ||
481 | }; | ||
482 | |||
483 | static struct platform_device at91sam9263_spi0_device = { | ||
484 | .name = "atmel_spi", | ||
485 | .id = 0, | ||
486 | .dev = { | ||
487 | .dma_mask = &spi_dmamask, | ||
488 | .coherent_dma_mask = 0xffffffff, | ||
489 | }, | ||
490 | .resource = spi0_resources, | ||
491 | .num_resources = ARRAY_SIZE(spi0_resources), | ||
492 | }; | ||
493 | |||
494 | static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA5, AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PB11 }; | ||
495 | |||
496 | static struct resource spi1_resources[] = { | ||
497 | [0] = { | ||
498 | .start = AT91SAM9263_BASE_SPI1, | ||
499 | .end = AT91SAM9263_BASE_SPI1 + SZ_16K - 1, | ||
500 | .flags = IORESOURCE_MEM, | ||
501 | }, | ||
502 | [1] = { | ||
503 | .start = AT91SAM9263_ID_SPI1, | ||
504 | .end = AT91SAM9263_ID_SPI1, | ||
505 | .flags = IORESOURCE_IRQ, | ||
506 | }, | ||
507 | }; | ||
508 | |||
509 | static struct platform_device at91sam9263_spi1_device = { | ||
510 | .name = "atmel_spi", | ||
511 | .id = 1, | ||
512 | .dev = { | ||
513 | .dma_mask = &spi_dmamask, | ||
514 | .coherent_dma_mask = 0xffffffff, | ||
515 | }, | ||
516 | .resource = spi1_resources, | ||
517 | .num_resources = ARRAY_SIZE(spi1_resources), | ||
518 | }; | ||
519 | |||
520 | static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB15, AT91_PIN_PB16, AT91_PIN_PB17, AT91_PIN_PB18 }; | ||
521 | |||
522 | void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) | ||
523 | { | ||
524 | int i; | ||
525 | unsigned long cs_pin; | ||
526 | short enable_spi0 = 0; | ||
527 | short enable_spi1 = 0; | ||
528 | |||
529 | /* Choose SPI chip-selects */ | ||
530 | for (i = 0; i < nr_devices; i++) { | ||
531 | if (devices[i].controller_data) | ||
532 | cs_pin = (unsigned long) devices[i].controller_data; | ||
533 | else if (devices[i].bus_num == 0) | ||
534 | cs_pin = spi0_standard_cs[devices[i].chip_select]; | ||
535 | else | ||
536 | cs_pin = spi1_standard_cs[devices[i].chip_select]; | ||
537 | |||
538 | if (devices[i].bus_num == 0) | ||
539 | enable_spi0 = 1; | ||
540 | else | ||
541 | enable_spi1 = 1; | ||
542 | |||
543 | /* enable chip-select pin */ | ||
544 | at91_set_gpio_output(cs_pin, 1); | ||
545 | |||
546 | /* pass chip-select pin to driver */ | ||
547 | devices[i].controller_data = (void *) cs_pin; | ||
548 | } | ||
549 | |||
550 | spi_register_board_info(devices, nr_devices); | ||
551 | |||
552 | /* Configure SPI bus(es) */ | ||
553 | if (enable_spi0) { | ||
554 | at91_set_B_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ | ||
555 | at91_set_B_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ | ||
556 | at91_set_B_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */ | ||
557 | |||
558 | at91_clock_associate("spi0_clk", &at91sam9263_spi0_device.dev, "spi_clk"); | ||
559 | platform_device_register(&at91sam9263_spi0_device); | ||
560 | } | ||
561 | if (enable_spi1) { | ||
562 | at91_set_A_periph(AT91_PIN_PB12, 0); /* SPI1_MISO */ | ||
563 | at91_set_A_periph(AT91_PIN_PB13, 0); /* SPI1_MOSI */ | ||
564 | at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_SPCK */ | ||
565 | |||
566 | at91_clock_associate("spi1_clk", &at91sam9263_spi1_device.dev, "spi_clk"); | ||
567 | platform_device_register(&at91sam9263_spi1_device); | ||
568 | } | ||
569 | } | ||
570 | #else | ||
571 | void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} | ||
572 | #endif | ||
573 | |||
574 | |||
575 | /* -------------------------------------------------------------------- | ||
576 | * LEDs | ||
577 | * -------------------------------------------------------------------- */ | ||
578 | |||
579 | #if defined(CONFIG_LEDS) | ||
580 | u8 at91_leds_cpu; | ||
581 | u8 at91_leds_timer; | ||
582 | |||
583 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) | ||
584 | { | ||
585 | /* Enable GPIO to access the LEDs */ | ||
586 | at91_set_gpio_output(cpu_led, 1); | ||
587 | at91_set_gpio_output(timer_led, 1); | ||
588 | |||
589 | at91_leds_cpu = cpu_led; | ||
590 | at91_leds_timer = timer_led; | ||
591 | } | ||
592 | #else | ||
593 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} | ||
594 | #endif | ||
595 | |||
596 | |||
597 | /* -------------------------------------------------------------------- | ||
598 | * UART | ||
599 | * -------------------------------------------------------------------- */ | ||
600 | |||
601 | #if defined(CONFIG_SERIAL_ATMEL) | ||
602 | |||
603 | static struct resource dbgu_resources[] = { | ||
604 | [0] = { | ||
605 | .start = AT91_VA_BASE_SYS + AT91_DBGU, | ||
606 | .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, | ||
607 | .flags = IORESOURCE_MEM, | ||
608 | }, | ||
609 | [1] = { | ||
610 | .start = AT91_ID_SYS, | ||
611 | .end = AT91_ID_SYS, | ||
612 | .flags = IORESOURCE_IRQ, | ||
613 | }, | ||
614 | }; | ||
615 | |||
616 | static struct atmel_uart_data dbgu_data = { | ||
617 | .use_dma_tx = 0, | ||
618 | .use_dma_rx = 0, /* DBGU not capable of receive DMA */ | ||
619 | .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), | ||
620 | }; | ||
621 | |||
622 | static struct platform_device at91sam9263_dbgu_device = { | ||
623 | .name = "atmel_usart", | ||
624 | .id = 0, | ||
625 | .dev = { | ||
626 | .platform_data = &dbgu_data, | ||
627 | .coherent_dma_mask = 0xffffffff, | ||
628 | }, | ||
629 | .resource = dbgu_resources, | ||
630 | .num_resources = ARRAY_SIZE(dbgu_resources), | ||
631 | }; | ||
632 | |||
633 | static inline void configure_dbgu_pins(void) | ||
634 | { | ||
635 | at91_set_A_periph(AT91_PIN_PC30, 0); /* DRXD */ | ||
636 | at91_set_A_periph(AT91_PIN_PC31, 1); /* DTXD */ | ||
637 | } | ||
638 | |||
639 | static struct resource uart0_resources[] = { | ||
640 | [0] = { | ||
641 | .start = AT91SAM9263_BASE_US0, | ||
642 | .end = AT91SAM9263_BASE_US0 + SZ_16K - 1, | ||
643 | .flags = IORESOURCE_MEM, | ||
644 | }, | ||
645 | [1] = { | ||
646 | .start = AT91SAM9263_ID_US0, | ||
647 | .end = AT91SAM9263_ID_US0, | ||
648 | .flags = IORESOURCE_IRQ, | ||
649 | }, | ||
650 | }; | ||
651 | |||
652 | static struct atmel_uart_data uart0_data = { | ||
653 | .use_dma_tx = 1, | ||
654 | .use_dma_rx = 1, | ||
655 | }; | ||
656 | |||
657 | static struct platform_device at91sam9263_uart0_device = { | ||
658 | .name = "atmel_usart", | ||
659 | .id = 1, | ||
660 | .dev = { | ||
661 | .platform_data = &uart0_data, | ||
662 | .coherent_dma_mask = 0xffffffff, | ||
663 | }, | ||
664 | .resource = uart0_resources, | ||
665 | .num_resources = ARRAY_SIZE(uart0_resources), | ||
666 | }; | ||
667 | |||
668 | static inline void configure_usart0_pins(void) | ||
669 | { | ||
670 | at91_set_A_periph(AT91_PIN_PA26, 1); /* TXD0 */ | ||
671 | at91_set_A_periph(AT91_PIN_PA27, 0); /* RXD0 */ | ||
672 | at91_set_A_periph(AT91_PIN_PA28, 0); /* RTS0 */ | ||
673 | at91_set_A_periph(AT91_PIN_PA29, 0); /* CTS0 */ | ||
674 | } | ||
675 | |||
676 | static struct resource uart1_resources[] = { | ||
677 | [0] = { | ||
678 | .start = AT91SAM9263_BASE_US1, | ||
679 | .end = AT91SAM9263_BASE_US1 + SZ_16K - 1, | ||
680 | .flags = IORESOURCE_MEM, | ||
681 | }, | ||
682 | [1] = { | ||
683 | .start = AT91SAM9263_ID_US1, | ||
684 | .end = AT91SAM9263_ID_US1, | ||
685 | .flags = IORESOURCE_IRQ, | ||
686 | }, | ||
687 | }; | ||
688 | |||
689 | static struct atmel_uart_data uart1_data = { | ||
690 | .use_dma_tx = 1, | ||
691 | .use_dma_rx = 1, | ||
692 | }; | ||
693 | |||
694 | static struct platform_device at91sam9263_uart1_device = { | ||
695 | .name = "atmel_usart", | ||
696 | .id = 2, | ||
697 | .dev = { | ||
698 | .platform_data = &uart1_data, | ||
699 | .coherent_dma_mask = 0xffffffff, | ||
700 | }, | ||
701 | .resource = uart1_resources, | ||
702 | .num_resources = ARRAY_SIZE(uart1_resources), | ||
703 | }; | ||
704 | |||
705 | static inline void configure_usart1_pins(void) | ||
706 | { | ||
707 | at91_set_A_periph(AT91_PIN_PD0, 1); /* TXD1 */ | ||
708 | at91_set_A_periph(AT91_PIN_PD1, 0); /* RXD1 */ | ||
709 | at91_set_B_periph(AT91_PIN_PD7, 0); /* RTS1 */ | ||
710 | at91_set_B_periph(AT91_PIN_PD8, 0); /* CTS1 */ | ||
711 | } | ||
712 | |||
713 | static struct resource uart2_resources[] = { | ||
714 | [0] = { | ||
715 | .start = AT91SAM9263_BASE_US2, | ||
716 | .end = AT91SAM9263_BASE_US2 + SZ_16K - 1, | ||
717 | .flags = IORESOURCE_MEM, | ||
718 | }, | ||
719 | [1] = { | ||
720 | .start = AT91SAM9263_ID_US2, | ||
721 | .end = AT91SAM9263_ID_US2, | ||
722 | .flags = IORESOURCE_IRQ, | ||
723 | }, | ||
724 | }; | ||
725 | |||
726 | static struct atmel_uart_data uart2_data = { | ||
727 | .use_dma_tx = 1, | ||
728 | .use_dma_rx = 1, | ||
729 | }; | ||
730 | |||
731 | static struct platform_device at91sam9263_uart2_device = { | ||
732 | .name = "atmel_usart", | ||
733 | .id = 3, | ||
734 | .dev = { | ||
735 | .platform_data = &uart2_data, | ||
736 | .coherent_dma_mask = 0xffffffff, | ||
737 | }, | ||
738 | .resource = uart2_resources, | ||
739 | .num_resources = ARRAY_SIZE(uart2_resources), | ||
740 | }; | ||
741 | |||
742 | static inline void configure_usart2_pins(void) | ||
743 | { | ||
744 | at91_set_A_periph(AT91_PIN_PD2, 1); /* TXD2 */ | ||
745 | at91_set_A_periph(AT91_PIN_PD3, 0); /* RXD2 */ | ||
746 | at91_set_B_periph(AT91_PIN_PD5, 0); /* RTS2 */ | ||
747 | at91_set_B_periph(AT91_PIN_PD6, 0); /* CTS2 */ | ||
748 | } | ||
749 | |||
750 | struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ | ||
751 | struct platform_device *atmel_default_console_device; /* the serial console device */ | ||
752 | |||
753 | void __init at91_init_serial(struct at91_uart_config *config) | ||
754 | { | ||
755 | int i; | ||
756 | |||
757 | /* Fill in list of supported UARTs */ | ||
758 | for (i = 0; i < config->nr_tty; i++) { | ||
759 | switch (config->tty_map[i]) { | ||
760 | case 0: | ||
761 | configure_usart0_pins(); | ||
762 | at91_uarts[i] = &at91sam9263_uart0_device; | ||
763 | at91_clock_associate("usart0_clk", &at91sam9263_uart0_device.dev, "usart"); | ||
764 | break; | ||
765 | case 1: | ||
766 | configure_usart1_pins(); | ||
767 | at91_uarts[i] = &at91sam9263_uart1_device; | ||
768 | at91_clock_associate("usart1_clk", &at91sam9263_uart1_device.dev, "usart"); | ||
769 | break; | ||
770 | case 2: | ||
771 | configure_usart2_pins(); | ||
772 | at91_uarts[i] = &at91sam9263_uart2_device; | ||
773 | at91_clock_associate("usart2_clk", &at91sam9263_uart2_device.dev, "usart"); | ||
774 | break; | ||
775 | case 3: | ||
776 | configure_dbgu_pins(); | ||
777 | at91_uarts[i] = &at91sam9263_dbgu_device; | ||
778 | at91_clock_associate("mck", &at91sam9263_dbgu_device.dev, "usart"); | ||
779 | break; | ||
780 | default: | ||
781 | continue; | ||
782 | } | ||
783 | at91_uarts[i]->id = i; /* update ID number to mapped ID */ | ||
784 | } | ||
785 | |||
786 | /* Set serial console device */ | ||
787 | if (config->console_tty < ATMEL_MAX_UART) | ||
788 | atmel_default_console_device = at91_uarts[config->console_tty]; | ||
789 | if (!atmel_default_console_device) | ||
790 | printk(KERN_INFO "AT91: No default serial console defined.\n"); | ||
791 | } | ||
792 | |||
793 | void __init at91_add_device_serial(void) | ||
794 | { | ||
795 | int i; | ||
796 | |||
797 | for (i = 0; i < ATMEL_MAX_UART; i++) { | ||
798 | if (at91_uarts[i]) | ||
799 | platform_device_register(at91_uarts[i]); | ||
800 | } | ||
801 | } | ||
802 | #else | ||
803 | void __init at91_init_serial(struct at91_uart_config *config) {} | ||
804 | void __init at91_add_device_serial(void) {} | ||
805 | #endif | ||
806 | |||
807 | |||
808 | /* -------------------------------------------------------------------- */ | ||
809 | /* | ||
810 | * These devices are always present and don't need any board-specific | ||
811 | * setup. | ||
812 | */ | ||
813 | static int __init at91_add_standard_devices(void) | ||
814 | { | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | arch_initcall(at91_add_standard_devices); | ||
diff --git a/arch/arm/mach-at91rm9200/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index 99df5f6ee42e..a4dded27fa16 100644 --- a/arch/arm/mach-at91rm9200/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c | 2 | * linux/arch/arm/mach-at91/at91sam926x_time.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France | 4 | * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France |
5 | * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France | 5 | * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France |
@@ -30,7 +30,6 @@ | |||
30 | * Returns number of microseconds since last timer interrupt. Note that interrupts | 30 | * Returns number of microseconds since last timer interrupt. Note that interrupts |
31 | * will have been disabled by do_gettimeofday() | 31 | * will have been disabled by do_gettimeofday() |
32 | * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. | 32 | * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. |
33 | * 'tick' is usecs per jiffy (linux/timex.h). | ||
34 | */ | 33 | */ |
35 | static unsigned long at91sam926x_gettimeoffset(void) | 34 | static unsigned long at91sam926x_gettimeoffset(void) |
36 | { | 35 | { |
@@ -39,7 +38,7 @@ static unsigned long at91sam926x_gettimeoffset(void) | |||
39 | 38 | ||
40 | elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */ | 39 | elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */ |
41 | 40 | ||
42 | return (unsigned long)(elapsed * 1000000) / LATCH; | 41 | return (unsigned long)(elapsed * jiffies_to_usecs(1)) / LATCH; |
43 | } | 42 | } |
44 | 43 | ||
45 | /* | 44 | /* |
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91/board-1arm.c index 971c3e2d8e36..2d3d4b6f7b02 100644 --- a/arch/arm/mach-at91rm9200/board-1arm.c +++ b/arch/arm/mach-at91/board-1arm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-1arm.c | 2 | * linux/arch/arm/mach-at91/board-1arm.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * | 5 | * |
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c index 654f0379550a..b4518619063a 100644 --- a/arch/arm/mach-at91rm9200/board-carmeva.c +++ b/arch/arm/mach-at91/board-carmeva.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-carmeva.c | 2 | * linux/arch/arm/mach-at91/board-carmeva.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Peer Georgi | 4 | * Copyright (c) 2005 Peer Georgi |
5 | * Conitec Datasystems | 5 | * Conitec Datasystems |
@@ -134,7 +134,7 @@ static void __init carmeva_board_init(void) | |||
134 | /* Compact Flash */ | 134 | /* Compact Flash */ |
135 | // at91_add_device_cf(&carmeva_cf_data); | 135 | // at91_add_device_cf(&carmeva_cf_data); |
136 | /* MMC */ | 136 | /* MMC */ |
137 | at91_add_device_mmc(&carmeva_mmc_data); | 137 | at91_add_device_mmc(0, &carmeva_mmc_data); |
138 | } | 138 | } |
139 | 139 | ||
140 | MACHINE_START(CARMEVA, "Carmeva") | 140 | MACHINE_START(CARMEVA, "Carmeva") |
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91/board-csb337.c index b8bb8052607a..e18a41e61f0c 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91/board-csb337.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-csb337.c | 2 | * linux/arch/arm/mach-at91/board-csb337.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * | 5 | * |
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/spi/spi.h> | 26 | #include <linux/spi/spi.h> |
27 | #include <linux/mtd/physmap.h> | ||
27 | 28 | ||
28 | #include <asm/hardware.h> | 29 | #include <asm/hardware.h> |
29 | #include <asm/setup.h> | 30 | #include <asm/setup.h> |
@@ -112,6 +113,42 @@ static struct spi_board_info csb337_spi_devices[] = { | |||
112 | }, | 113 | }, |
113 | }; | 114 | }; |
114 | 115 | ||
116 | #define CSB_FLASH_BASE AT91_CHIPSELECT_0 | ||
117 | #define CSB_FLASH_SIZE 0x800000 | ||
118 | |||
119 | static struct mtd_partition csb_flash_partitions[] = { | ||
120 | { | ||
121 | .name = "uMON flash", | ||
122 | .offset = 0, | ||
123 | .size = MTDPART_SIZ_FULL, | ||
124 | .mask_flags = MTD_WRITEABLE, /* read only */ | ||
125 | } | ||
126 | }; | ||
127 | |||
128 | static struct physmap_flash_data csb_flash_data = { | ||
129 | .width = 2, | ||
130 | .parts = csb_flash_partitions, | ||
131 | .nr_parts = ARRAY_SIZE(csb_flash_partitions), | ||
132 | }; | ||
133 | |||
134 | static struct resource csb_flash_resources[] = { | ||
135 | { | ||
136 | .start = CSB_FLASH_BASE, | ||
137 | .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1, | ||
138 | .flags = IORESOURCE_MEM, | ||
139 | } | ||
140 | }; | ||
141 | |||
142 | static struct platform_device csb_flash = { | ||
143 | .name = "physmap-flash", | ||
144 | .id = 0, | ||
145 | .dev = { | ||
146 | .platform_data = &csb_flash_data, | ||
147 | }, | ||
148 | .resource = csb_flash_resources, | ||
149 | .num_resources = ARRAY_SIZE(csb_flash_resources), | ||
150 | }; | ||
151 | |||
115 | static void __init csb337_board_init(void) | 152 | static void __init csb337_board_init(void) |
116 | { | 153 | { |
117 | /* Serial */ | 154 | /* Serial */ |
@@ -130,7 +167,9 @@ static void __init csb337_board_init(void) | |||
130 | /* SPI */ | 167 | /* SPI */ |
131 | at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); | 168 | at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); |
132 | /* MMC */ | 169 | /* MMC */ |
133 | at91_add_device_mmc(&csb337_mmc_data); | 170 | at91_add_device_mmc(0, &csb337_mmc_data); |
171 | /* NOR flash */ | ||
172 | platform_device_register(&csb_flash); | ||
134 | } | 173 | } |
135 | 174 | ||
136 | MACHINE_START(CSB337, "Cogent CSB337") | 175 | MACHINE_START(CSB337, "Cogent CSB337") |
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91/board-csb637.c index a29fa0e822ce..77f04b935b3a 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91/board-csb637.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-csb637.c | 2 | * linux/arch/arm/mach-at91/board-csb637.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * | 5 | * |
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/mtd/physmap.h> | ||
26 | 27 | ||
27 | #include <asm/hardware.h> | 28 | #include <asm/hardware.h> |
28 | #include <asm/setup.h> | 29 | #include <asm/setup.h> |
@@ -81,6 +82,42 @@ static struct at91_udc_data __initdata csb637_udc_data = { | |||
81 | .pullup_pin = AT91_PIN_PB1, | 82 | .pullup_pin = AT91_PIN_PB1, |
82 | }; | 83 | }; |
83 | 84 | ||
85 | #define CSB_FLASH_BASE AT91_CHIPSELECT_0 | ||
86 | #define CSB_FLASH_SIZE 0x1000000 | ||
87 | |||
88 | static struct mtd_partition csb_flash_partitions[] = { | ||
89 | { | ||
90 | .name = "uMON flash", | ||
91 | .offset = 0, | ||
92 | .size = MTDPART_SIZ_FULL, | ||
93 | .mask_flags = MTD_WRITEABLE, /* read only */ | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | static struct physmap_flash_data csb_flash_data = { | ||
98 | .width = 2, | ||
99 | .parts = csb_flash_partitions, | ||
100 | .nr_parts = ARRAY_SIZE(csb_flash_partitions), | ||
101 | }; | ||
102 | |||
103 | static struct resource csb_flash_resources[] = { | ||
104 | { | ||
105 | .start = CSB_FLASH_BASE, | ||
106 | .end = CSB_FLASH_BASE + CSB_FLASH_SIZE - 1, | ||
107 | .flags = IORESOURCE_MEM, | ||
108 | } | ||
109 | }; | ||
110 | |||
111 | static struct platform_device csb_flash = { | ||
112 | .name = "physmap-flash", | ||
113 | .id = 0, | ||
114 | .dev = { | ||
115 | .platform_data = &csb_flash_data, | ||
116 | }, | ||
117 | .resource = csb_flash_resources, | ||
118 | .num_resources = ARRAY_SIZE(csb_flash_resources), | ||
119 | }; | ||
120 | |||
84 | static void __init csb637_board_init(void) | 121 | static void __init csb637_board_init(void) |
85 | { | 122 | { |
86 | /* Serial */ | 123 | /* Serial */ |
@@ -95,6 +132,8 @@ static void __init csb637_board_init(void) | |||
95 | at91_add_device_i2c(); | 132 | at91_add_device_i2c(); |
96 | /* SPI */ | 133 | /* SPI */ |
97 | at91_add_device_spi(NULL, 0); | 134 | at91_add_device_spi(NULL, 0); |
135 | /* NOR flash */ | ||
136 | platform_device_register(&csb_flash); | ||
98 | } | 137 | } |
99 | 138 | ||
100 | MACHINE_START(CSB637, "Cogent CSB637") | 139 | MACHINE_START(CSB637, "Cogent CSB637") |
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91/board-dk.c index 7522bf91bce8..6043c38c0a9e 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91/board-dk.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-dk.c | 2 | * linux/arch/arm/mach-at91/board-dk.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * | 5 | * |
@@ -194,7 +194,7 @@ static void __init dk_board_init(void) | |||
194 | #else | 194 | #else |
195 | /* MMC */ | 195 | /* MMC */ |
196 | at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ | 196 | at91_set_gpio_output(AT91_PIN_PB7, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ |
197 | at91_add_device_mmc(&dk_mmc_data); | 197 | at91_add_device_mmc(0, &dk_mmc_data); |
198 | #endif | 198 | #endif |
199 | /* NAND */ | 199 | /* NAND */ |
200 | at91_add_device_nand(&dk_nand_data); | 200 | at91_add_device_nand(&dk_nand_data); |
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c index 80b72cf7264c..20458b5548f0 100644 --- a/arch/arm/mach-at91rm9200/board-eb9200.c +++ b/arch/arm/mach-at91/board-eb9200.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-eb9200.c | 2 | * linux/arch/arm/mach-at91/board-eb9200.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest | 4 | * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest |
5 | * by Andrew Patrikalakis | 5 | * by Andrew Patrikalakis |
@@ -109,7 +109,7 @@ static void __init eb9200_board_init(void) | |||
109 | at91_add_device_spi(NULL, 0); | 109 | at91_add_device_spi(NULL, 0); |
110 | /* MMC */ | 110 | /* MMC */ |
111 | /* only supports 1 or 4 bit interface, not wired through to SPI */ | 111 | /* only supports 1 or 4 bit interface, not wired through to SPI */ |
112 | at91_add_device_mmc(&eb9200_mmc_data); | 112 | at91_add_device_mmc(0, &eb9200_mmc_data); |
113 | } | 113 | } |
114 | 114 | ||
115 | MACHINE_START(ATEB9200, "Embest ATEB9200") | 115 | MACHINE_START(ATEB9200, "Embest ATEB9200") |
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91/board-ek.c index c4fdb415f20e..322fdd75a1e4 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91/board-ek.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-ek.c | 2 | * linux/arch/arm/mach-at91/board-ek.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * | 5 | * |
@@ -154,7 +154,7 @@ static void __init ek_board_init(void) | |||
154 | #else | 154 | #else |
155 | /* MMC */ | 155 | /* MMC */ |
156 | at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ | 156 | at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ |
157 | at91_add_device_mmc(&ek_mmc_data); | 157 | at91_add_device_mmc(0, &ek_mmc_data); |
158 | #endif | 158 | #endif |
159 | /* NOR Flash */ | 159 | /* NOR Flash */ |
160 | platform_device_register(&ek_flash); | 160 | platform_device_register(&ek_flash); |
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91/board-kafa.c index 6ef3c4879829..c77d84ce9cae 100644 --- a/arch/arm/mach-at91rm9200/board-kafa.c +++ b/arch/arm/mach-at91/board-kafa.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-kafa.c | 2 | * linux/arch/arm/mach-at91/board-kafa.c |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Sperry-Sun | 4 | * Copyright (C) 2006 Sperry-Sun |
5 | * | 5 | * |
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c index 759d8191854f..76f6e1e553ea 100644 --- a/arch/arm/mach-at91rm9200/board-kb9202.c +++ b/arch/arm/mach-at91/board-kb9202.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-kb9202.c | 2 | * linux/arch/arm/mach-at91/board-kb9202.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 kb_admin | 4 | * Copyright (c) 2005 kb_admin |
5 | * KwikByte, Inc. | 5 | * KwikByte, Inc. |
@@ -122,7 +122,7 @@ static void __init kb9202_board_init(void) | |||
122 | /* USB Device */ | 122 | /* USB Device */ |
123 | at91_add_device_udc(&kb9202_udc_data); | 123 | at91_add_device_udc(&kb9202_udc_data); |
124 | /* MMC */ | 124 | /* MMC */ |
125 | at91_add_device_mmc(&kb9202_mmc_data); | 125 | at91_add_device_mmc(0, &kb9202_mmc_data); |
126 | /* I2C */ | 126 | /* I2C */ |
127 | at91_add_device_i2c(); | 127 | at91_add_device_i2c(); |
128 | /* SPI */ | 128 | /* SPI */ |
diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c index da5d58ac870b..57fb4499d969 100644 --- a/arch/arm/mach-at91rm9200/board-sam9260ek.c +++ b/arch/arm/mach-at91/board-sam9260ek.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-ek.c | 2 | * linux/arch/arm/mach-at91/board-sam9260ek.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * Copyright (C) 2006 Atmel | 5 | * Copyright (C) 2006 Atmel |
@@ -118,7 +118,7 @@ static struct spi_board_info ek_spi_devices[] = { | |||
118 | /* | 118 | /* |
119 | * MACB Ethernet device | 119 | * MACB Ethernet device |
120 | */ | 120 | */ |
121 | static struct __initdata eth_platform_data ek_macb_data = { | 121 | static struct __initdata at91_eth_data ek_macb_data = { |
122 | .phy_irq_pin = AT91_PIN_PA7, | 122 | .phy_irq_pin = AT91_PIN_PA7, |
123 | .is_rmii = 1, | 123 | .is_rmii = 1, |
124 | }; | 124 | }; |
@@ -187,7 +187,7 @@ static void __init ek_board_init(void) | |||
187 | /* Ethernet */ | 187 | /* Ethernet */ |
188 | at91_add_device_eth(&ek_macb_data); | 188 | at91_add_device_eth(&ek_macb_data); |
189 | /* MMC */ | 189 | /* MMC */ |
190 | at91_add_device_mmc(&ek_mmc_data); | 190 | at91_add_device_mmc(0, &ek_mmc_data); |
191 | } | 191 | } |
192 | 192 | ||
193 | MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") | 193 | MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") |
diff --git a/arch/arm/mach-at91rm9200/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c index 30b490d8886b..b7e772467cf6 100644 --- a/arch/arm/mach-at91rm9200/board-sam9261ek.c +++ b/arch/arm/mach-at91/board-sam9261ek.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/board-ek.c | 2 | * linux/arch/arm/mach-at91/board-sam9261ek.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 SAN People | 4 | * Copyright (C) 2005 SAN People |
5 | * Copyright (C) 2006 Atmel | 5 | * Copyright (C) 2006 Atmel |
@@ -243,7 +243,7 @@ static void __init ek_board_init(void) | |||
243 | at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); | 243 | at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); |
244 | #else | 244 | #else |
245 | /* MMC */ | 245 | /* MMC */ |
246 | at91_add_device_mmc(&ek_mmc_data); | 246 | at91_add_device_mmc(0, &ek_mmc_data); |
247 | #endif | 247 | #endif |
248 | } | 248 | } |
249 | 249 | ||
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c new file mode 100644 index 000000000000..8fdce11a880c --- /dev/null +++ b/arch/arm/mach-at91/board-sam9263ek.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-at91/board-sam9263ek.c | ||
3 | * | ||
4 | * Copyright (C) 2005 SAN People | ||
5 | * Copyright (C) 2007 Atmel Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | |||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/setup.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <asm/irq.h> | ||
33 | |||
34 | #include <asm/mach/arch.h> | ||
35 | #include <asm/mach/map.h> | ||
36 | #include <asm/mach/irq.h> | ||
37 | |||
38 | #include <asm/arch/board.h> | ||
39 | #include <asm/arch/gpio.h> | ||
40 | #include <asm/arch/at91sam926x_mc.h> | ||
41 | |||
42 | #include "generic.h" | ||
43 | |||
44 | |||
45 | /* | ||
46 | * Serial port configuration. | ||
47 | * 0 .. 2 = USART0 .. USART2 | ||
48 | * 3 = DBGU | ||
49 | */ | ||
50 | static struct at91_uart_config __initdata ek_uart_config = { | ||
51 | .console_tty = 0, /* ttyS0 */ | ||
52 | .nr_tty = 2, | ||
53 | .tty_map = { 3, 0, -1, -1, } /* ttyS0, ..., ttyS3 */ | ||
54 | }; | ||
55 | |||
56 | static void __init ek_map_io(void) | ||
57 | { | ||
58 | /* Initialize processor: 16.367 MHz crystal */ | ||
59 | at91sam9263_initialize(16367660); | ||
60 | |||
61 | /* Setup the serial ports and console */ | ||
62 | at91_init_serial(&ek_uart_config); | ||
63 | } | ||
64 | |||
65 | static void __init ek_init_irq(void) | ||
66 | { | ||
67 | at91sam9263_init_interrupts(NULL); | ||
68 | } | ||
69 | |||
70 | |||
71 | /* | ||
72 | * USB Host port | ||
73 | */ | ||
74 | static struct at91_usbh_data __initdata ek_usbh_data = { | ||
75 | .ports = 2, | ||
76 | .vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 }, | ||
77 | }; | ||
78 | |||
79 | /* | ||
80 | * USB Device port | ||
81 | */ | ||
82 | static struct at91_udc_data __initdata ek_udc_data = { | ||
83 | .vbus_pin = AT91_PIN_PA25, | ||
84 | .pullup_pin = 0, /* pull-up driven by UDC */ | ||
85 | }; | ||
86 | |||
87 | |||
88 | /* | ||
89 | * SPI devices. | ||
90 | */ | ||
91 | static struct spi_board_info ek_spi_devices[] = { | ||
92 | #if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) | ||
93 | { /* DataFlash card */ | ||
94 | .modalias = "mtd_dataflash", | ||
95 | .chip_select = 0, | ||
96 | .max_speed_hz = 15 * 1000 * 1000, | ||
97 | .bus_num = 0, | ||
98 | }, | ||
99 | #endif | ||
100 | }; | ||
101 | |||
102 | |||
103 | /* | ||
104 | * MCI (SD/MMC) | ||
105 | */ | ||
106 | static struct at91_mmc_data __initdata ek_mmc_data = { | ||
107 | .wire4 = 1, | ||
108 | .det_pin = AT91_PIN_PE18, | ||
109 | .wp_pin = AT91_PIN_PE19, | ||
110 | // .vcc_pin = ... not connected | ||
111 | }; | ||
112 | |||
113 | |||
114 | /* | ||
115 | * NAND flash | ||
116 | */ | ||
117 | static struct mtd_partition __initdata ek_nand_partition[] = { | ||
118 | { | ||
119 | .name = "Partition 1", | ||
120 | .offset = 0, | ||
121 | .size = 64 * 1024 * 1024, | ||
122 | }, | ||
123 | { | ||
124 | .name = "Partition 2", | ||
125 | .offset = 64 * 1024 * 1024, | ||
126 | .size = MTDPART_SIZ_FULL, | ||
127 | }, | ||
128 | }; | ||
129 | |||
130 | static struct mtd_partition *nand_partitions(int size, int *num_partitions) | ||
131 | { | ||
132 | *num_partitions = ARRAY_SIZE(ek_nand_partition); | ||
133 | return ek_nand_partition; | ||
134 | } | ||
135 | |||
136 | static struct at91_nand_data __initdata ek_nand_data = { | ||
137 | .ale = 21, | ||
138 | .cle = 22, | ||
139 | // .det_pin = ... not connected | ||
140 | .rdy_pin = AT91_PIN_PA22, | ||
141 | .enable_pin = AT91_PIN_PD15, | ||
142 | .partition_info = nand_partitions, | ||
143 | #if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) | ||
144 | .bus_width_16 = 1, | ||
145 | #else | ||
146 | .bus_width_16 = 0, | ||
147 | #endif | ||
148 | }; | ||
149 | |||
150 | |||
151 | static void __init ek_board_init(void) | ||
152 | { | ||
153 | /* Serial */ | ||
154 | at91_add_device_serial(); | ||
155 | /* USB Host */ | ||
156 | at91_add_device_usbh(&ek_usbh_data); | ||
157 | /* USB Device */ | ||
158 | at91_add_device_udc(&ek_udc_data); | ||
159 | /* SPI */ | ||
160 | at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); | ||
161 | /* MMC */ | ||
162 | at91_add_device_mmc(1, &ek_mmc_data); | ||
163 | /* NAND */ | ||
164 | at91_add_device_nand(&ek_nand_data); | ||
165 | } | ||
166 | |||
167 | MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK") | ||
168 | /* Maintainer: Atmel */ | ||
169 | .phys_io = AT91_BASE_SYS, | ||
170 | .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, | ||
171 | .boot_params = AT91_SDRAM_BASE + 0x100, | ||
172 | .timer = &at91sam926x_timer, | ||
173 | .map_io = ek_map_io, | ||
174 | .init_irq = ek_init_irq, | ||
175 | .init_machine = ek_board_init, | ||
176 | MACHINE_END | ||
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91/clock.c index 4dee21fefe5a..f6cb74806043 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91/clock.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/clock.c | 2 | * linux/arch/arm/mach-at91/clock.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 David Brownell | 4 | * Copyright (C) 2005 David Brownell |
5 | * Copyright (C) 2005 Ivan Kokshaysky | 5 | * Copyright (C) 2005 Ivan Kokshaysky |
@@ -525,27 +525,6 @@ fail: | |||
525 | return 0; | 525 | return 0; |
526 | } | 526 | } |
527 | 527 | ||
528 | /* | ||
529 | * Several unused clocks may be active. Turn them off. | ||
530 | */ | ||
531 | static void __init at91_periphclk_reset(void) | ||
532 | { | ||
533 | unsigned long reg; | ||
534 | struct clk *clk; | ||
535 | |||
536 | reg = at91_sys_read(AT91_PMC_PCSR); | ||
537 | |||
538 | list_for_each_entry(clk, &clocks, node) { | ||
539 | if (clk->mode != pmc_periph_mode) | ||
540 | continue; | ||
541 | |||
542 | if (clk->users > 0) | ||
543 | reg &= ~clk->pmc_mask; | ||
544 | } | ||
545 | |||
546 | at91_sys_write(AT91_PMC_PCDR, reg); | ||
547 | } | ||
548 | |||
549 | static struct clk *const standard_pmc_clocks[] __initdata = { | 528 | static struct clk *const standard_pmc_clocks[] __initdata = { |
550 | /* four primary clocks */ | 529 | /* four primary clocks */ |
551 | &clk32k, | 530 | &clk32k, |
@@ -586,7 +565,7 @@ int __init at91_clock_init(unsigned long main_clock) | |||
586 | pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); | 565 | pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); |
587 | 566 | ||
588 | /* | 567 | /* |
589 | * USB clock init: choose 48 MHz PLLB value, turn all clocks off, | 568 | * USB clock init: choose 48 MHz PLLB value, |
590 | * disable 48MHz clock during usb peripheral suspend. | 569 | * disable 48MHz clock during usb peripheral suspend. |
591 | * | 570 | * |
592 | * REVISIT: assumes MCK doesn't derive from PLLB! | 571 | * REVISIT: assumes MCK doesn't derive from PLLB! |
@@ -596,16 +575,10 @@ int __init at91_clock_init(unsigned long main_clock) | |||
596 | if (cpu_is_at91rm9200()) { | 575 | if (cpu_is_at91rm9200()) { |
597 | uhpck.pmc_mask = AT91RM9200_PMC_UHP; | 576 | uhpck.pmc_mask = AT91RM9200_PMC_UHP; |
598 | udpck.pmc_mask = AT91RM9200_PMC_UDP; | 577 | udpck.pmc_mask = AT91RM9200_PMC_UDP; |
599 | at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); | ||
600 | at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); | 578 | at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); |
601 | } else if (cpu_is_at91sam9260()) { | 579 | } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) { |
602 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; | 580 | uhpck.pmc_mask = AT91SAM926x_PMC_UHP; |
603 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; | 581 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; |
604 | at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); | ||
605 | } else if (cpu_is_at91sam9261()) { | ||
606 | uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); | ||
607 | udpck.pmc_mask = AT91SAM926x_PMC_UDP; | ||
608 | at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); | ||
609 | } | 582 | } |
610 | at91_sys_write(AT91_CKGR_PLLBR, 0); | 583 | at91_sys_write(AT91_CKGR_PLLBR, 0); |
611 | 584 | ||
@@ -634,11 +607,34 @@ int __init at91_clock_init(unsigned long main_clock) | |||
634 | (unsigned) main_clock / 1000000, | 607 | (unsigned) main_clock / 1000000, |
635 | ((unsigned) main_clock % 1000000) / 1000); | 608 | ((unsigned) main_clock % 1000000) / 1000); |
636 | 609 | ||
637 | /* disable all programmable clocks */ | 610 | return 0; |
638 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); | 611 | } |
612 | |||
613 | /* | ||
614 | * Several unused clocks may be active. Turn them off. | ||
615 | */ | ||
616 | static int __init at91_clock_reset(void) | ||
617 | { | ||
618 | unsigned long pcdr = 0; | ||
619 | unsigned long scdr = 0; | ||
620 | struct clk *clk; | ||
621 | |||
622 | list_for_each_entry(clk, &clocks, node) { | ||
623 | if (clk->users > 0) | ||
624 | continue; | ||
625 | |||
626 | if (clk->mode == pmc_periph_mode) | ||
627 | pcdr |= clk->pmc_mask; | ||
628 | |||
629 | if (clk->mode == pmc_sys_mode) | ||
630 | scdr |= clk->pmc_mask; | ||
631 | |||
632 | pr_debug("Clocks: disable unused %s\n", clk->name); | ||
633 | } | ||
639 | 634 | ||
640 | /* disable all other unused peripheral clocks */ | 635 | at91_sys_write(AT91_PMC_PCDR, pcdr); |
641 | at91_periphclk_reset(); | 636 | at91_sys_write(AT91_PMC_SCDR, scdr); |
642 | 637 | ||
643 | return 0; | 638 | return 0; |
644 | } | 639 | } |
640 | late_initcall(at91_clock_reset); | ||
diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91/clock.h index b5c7a2eb2d1d..1ba3b95ff359 100644 --- a/arch/arm/mach-at91rm9200/clock.h +++ b/arch/arm/mach-at91/clock.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/clock.h | 2 | * linux/arch/arm/mach-at91/clock.h |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91/generic.h index 8c4d5a77d485..bda26221c522 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91/generic.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/generic.h | 2 | * linux/arch/arm/mach-at91/generic.h |
3 | * | 3 | * |
4 | * Copyright (C) 2005 David Brownell | 4 | * Copyright (C) 2005 David Brownell |
5 | * | 5 | * |
@@ -12,11 +12,13 @@ | |||
12 | extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); | 12 | extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); |
13 | extern void __init at91sam9260_initialize(unsigned long main_clock); | 13 | extern void __init at91sam9260_initialize(unsigned long main_clock); |
14 | extern void __init at91sam9261_initialize(unsigned long main_clock); | 14 | extern void __init at91sam9261_initialize(unsigned long main_clock); |
15 | extern void __init at91sam9263_initialize(unsigned long main_clock); | ||
15 | 16 | ||
16 | /* Interrupts */ | 17 | /* Interrupts */ |
17 | extern void __init at91rm9200_init_interrupts(unsigned int priority[]); | 18 | extern void __init at91rm9200_init_interrupts(unsigned int priority[]); |
18 | extern void __init at91sam9260_init_interrupts(unsigned int priority[]); | 19 | extern void __init at91sam9260_init_interrupts(unsigned int priority[]); |
19 | extern void __init at91sam9261_init_interrupts(unsigned int priority[]); | 20 | extern void __init at91sam9261_init_interrupts(unsigned int priority[]); |
21 | extern void __init at91sam9263_init_interrupts(unsigned int priority[]); | ||
20 | extern void __init at91_aic_init(unsigned int priority[]); | 22 | extern void __init at91_aic_init(unsigned int priority[]); |
21 | 23 | ||
22 | /* Timer */ | 24 | /* Timer */ |
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91/gpio.c index af22659c8a28..9b7495cd555d 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91/gpio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/gpio.c | 2 | * linux/arch/arm/mach-at91/gpio.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005 HP Labs | 4 | * Copyright (C) 2005 HP Labs |
5 | * | 5 | * |
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91/irq.c index 2148daafd29c..78a5cdb746dc 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91/irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-at91rm9200/irq.c | 2 | * linux/arch/arm/mach-at91/irq.c |
3 | * | 3 | * |
4 | * Copyright (C) 2004 SAN People | 4 | * Copyright (C) 2004 SAN People |
5 | * Copyright (C) 2004 ATMEL | 5 | * Copyright (C) 2004 ATMEL |
diff --git a/arch/arm/mach-at91rm9200/leds.c b/arch/arm/mach-at91/leds.c index 1a333730466e..0d5144973988 100644 --- a/arch/arm/mach-at91rm9200/leds.c +++ b/arch/arm/mach-at91/leds.c | |||
@@ -86,10 +86,6 @@ static int __init leds_init(void) | |||
86 | if (!at91_leds_timer || !at91_leds_cpu) | 86 | if (!at91_leds_timer || !at91_leds_cpu) |
87 | return -ENODEV; | 87 | return -ENODEV; |
88 | 88 | ||
89 | /* Enable PIO to access the LEDs */ | ||
90 | at91_set_gpio_output(at91_leds_timer, 1); | ||
91 | at91_set_gpio_output(at91_leds_cpu, 1); | ||
92 | |||
93 | leds_event = at91_leds_event; | 89 | leds_event = at91_leds_event; |
94 | 90 | ||
95 | leds_event(led_start); | 91 | leds_event(led_start); |
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91/pm.c index 67aa5572a3ea..b49bfda53d7f 100644 --- a/arch/arm/mach-at91rm9200/pm.c +++ b/arch/arm/mach-at91/pm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-at91rm9200/pm.c | 2 | * arch/arm/mach-at91/pm.c |
3 | * AT91 Power Management | 3 | * AT91 Power Management |
4 | * | 4 | * |
5 | * Copyright (C) 2005 David Brownell | 5 | * Copyright (C) 2005 David Brownell |
@@ -80,6 +80,8 @@ static int at91_pm_verify_clocks(void) | |||
80 | #warning "Check SAM9260 USB clocks" | 80 | #warning "Check SAM9260 USB clocks" |
81 | } else if (cpu_is_at91sam9261()) { | 81 | } else if (cpu_is_at91sam9261()) { |
82 | #warning "Check SAM9261 USB clocks" | 82 | #warning "Check SAM9261 USB clocks" |
83 | } else if (cpu_is_at91sam9263()) { | ||
84 | #warning "Check SAM9263 USB clocks" | ||
83 | } | 85 | } |
84 | 86 | ||
85 | #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS | 87 | #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS |
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 08ad782c1649..f174d1a3b11c 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/module.h> | ||
16 | #include <linux/string.h> | 17 | #include <linux/string.h> |
17 | #include <asm/div64.h> | 18 | #include <asm/div64.h> |
18 | #include <asm/hardware.h> | 19 | #include <asm/hardware.h> |
@@ -124,7 +125,7 @@ static unsigned long calc_pll_rate(u32 config_word) | |||
124 | return (unsigned long)rate; | 125 | return (unsigned long)rate; |
125 | } | 126 | } |
126 | 127 | ||
127 | void ep93xx_clock_init(void) | 128 | static 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 | } |
160 | arch_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 | *************************************************************************/ |
155 | static unsigned char gpio_int_enable[2]; | 155 | static unsigned char gpio_int_unmasked[3]; |
156 | static unsigned char gpio_int_type1[2]; | 156 | static unsigned char gpio_int_enabled[3]; |
157 | static unsigned char gpio_int_type2[2]; | 157 | static unsigned char gpio_int_type1[3]; |
158 | static unsigned char gpio_int_type2[3]; | ||
158 | 159 | ||
159 | static void update_gpio_ab_int_params(int port) | 160 | static 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 | *************************************************************************/ |
247 | static void ep93xx_gpio_ab_irq_handler(unsigned int irq, | 260 | static 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 | ||
270 | static void ep93xx_gpio_ab_irq_mask_ack(unsigned int irq) | 282 | static 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 | |||
289 | static 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 | ||
285 | static void ep93xx_gpio_ab_irq_mask(unsigned int irq) | 306 | static 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 | ||
294 | static void ep93xx_gpio_ab_irq_unmask(unsigned int irq) | 315 | static 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 | */ |
309 | static int ep93xx_gpio_ab_irq_type(unsigned int irq, unsigned int type) | 330 | static 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 | ||
338 | static struct irq_chip ep93xx_gpio_ab_irq_chip = { | 369 | static 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-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 | |||
10 | config REALVIEW_MPCORE | 10 | config 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 | ||
20 | config 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 | |||
19 | endmenu | 30 | endmenu |
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 | ||
150 | static void __init realview_eb_init(void) | 175 | static 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 | |||
9 | menu "S3C2400 Machines" | ||
10 | |||
11 | |||
12 | endmenu | ||
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 | |||
7 | obj-y := | ||
8 | obj-m := | ||
9 | obj-n := | ||
10 | obj- := | ||
11 | |||
12 | obj-$(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 @@ | |||
1 | if ARCH_S3C2410 | 1 | # arch/arm/mach-s3c2410/Kconfig |
2 | # | ||
3 | # Copyright 2007 Simtec Electronics | ||
4 | # | ||
5 | # Licensed under GPLv2 | ||
2 | 6 | ||
3 | menu "S3C24XX Implementations" | 7 | config 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 | ||
5 | config MACH_AML_M5900 | 17 | config 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 | ||
13 | config MACH_ANUBIS | 24 | config 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 | ||
21 | config MACH_OSIRIS | 29 | config 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 | ||
29 | config ARCH_BAST | 34 | config 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 | ||
40 | config BAST_PC104_IRQ | 40 | menu "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 | ||
48 | config PM_H1940 | 42 | config 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 | ||
53 | config ARCH_H1940 | 50 | config 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>. | 57 | config PM_H1940 |
58 | bool | ||
59 | help | ||
60 | Internal node for H1940 and related PM | ||
61 | 61 | ||
62 | config MACH_N30 | 62 | config 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>. | 68 | config ARCH_BAST |
69 | 69 | bool "Simtec Electronics BAST (EB2410ITX)" | |
70 | config MACH_SMDK | ||
71 | bool | ||
72 | help | ||
73 | Common machine code for SMDK2410 and SMDK2440 | ||
74 | |||
75 | config 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 | ||
83 | config ARCH_S3C2440 | 77 | config 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 | |||
90 | config 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 | |||
96 | config SMDK2440_CPU2442 | ||
97 | bool "SMDM2440 with S3C2442 CPU module" | ||
98 | depends on ARCH_S3C2440 | ||
99 | select CPU_S3C2442 | ||
100 | 82 | ||
101 | config MACH_S3C2413 | 83 | config 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 | ||
108 | config MACH_SMDK2413 | 91 | config 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 | ||
116 | config MACH_VR1000 | 99 | config 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 | 106 | config MACH_QT2410 |
124 | of Thorcom. Any queries, please contact Thorcom first. | 107 | bool "QT2410" |
125 | 108 | select CPU_S3C2410 | |
126 | config 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 | |||
136 | config 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 | |||
142 | config 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 | |||
148 | config 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 | ||
154 | endmenu | 112 | endmenu |
155 | 113 | ||
156 | config S3C2410_CLOCK | ||
157 | bool | ||
158 | help | ||
159 | Clock code for the S3C2410, and similar processors | ||
160 | |||
161 | config S3C2410_PM | ||
162 | bool | ||
163 | help | ||
164 | Power Management code common to S3C2410 and better | ||
165 | |||
166 | config 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 | |||
173 | config 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 | |||
184 | config 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 | |||
190 | config S3C2412_PM | ||
191 | bool | ||
192 | help | ||
193 | Internal config node to apply S3C2412 power management | ||
194 | |||
195 | config 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 | |||
202 | config 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 | |||
208 | config 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 | |||
217 | config 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 | |||
226 | comment "S3C2410 Boot" | ||
227 | |||
228 | config 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 | |||
246 | config 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 | |||
254 | comment "S3C2410 Setup" | ||
255 | |||
256 | config 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 | |||
264 | config 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 | |||
276 | config 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 | |||
284 | config 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 | |||
293 | config 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 | |||
303 | config 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 | |||
309 | config 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 | |||
321 | endif | ||
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. | 7 | obj-y := |
7 | 8 | obj-m := | |
8 | obj-y := cpu.o irq.o time.o gpio.o clock.o devs.o | 9 | obj-n := |
9 | obj-m := | 10 | obj- := |
10 | obj-n := | ||
11 | obj- := | ||
12 | obj-dma-y := | ||
13 | obj-dma-n := | ||
14 | |||
15 | # DMA | ||
16 | obj-$(CONFIG_S3C2410_DMA) += dma.o | ||
17 | |||
18 | # S3C2400 support files | ||
19 | obj-$(CONFIG_CPU_S3C2400) += s3c2400-gpio.o | ||
20 | |||
21 | # S3C2410 support files | ||
22 | 11 | ||
23 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o | 12 | obj-$(CONFIG_CPU_S3C2410) += s3c2410.o |
24 | obj-$(CONFIG_CPU_S3C2410) += s3c2410-gpio.o | 13 | obj-$(CONFIG_CPU_S3C2410) += irq.o |
25 | obj-$(CONFIG_CPU_S3C2410) += s3c2410-irq.o | 14 | obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o |
26 | 15 | obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o | |
27 | obj-$(CONFIG_S3C2410_PM) += s3c2410-pm.o s3c2410-sleep.o | 16 | obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o |
28 | obj-$(CONFIG_CPU_S3C2410_DMA) += s3c2410-dma.o | 17 | obj-$(CONFIG_S3C2410_GPIO) += gpio.o |
29 | 18 | obj-$(CONFIG_S3C2410_CLOCK) += clock.o | |
30 | # Power Management support | ||
31 | |||
32 | obj-$(CONFIG_PM) += pm.o sleep.o | ||
33 | obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o | ||
34 | obj-$(CONFIG_PM_H1940) += pm-h1940.o | ||
35 | |||
36 | # S3C2412 support | ||
37 | obj-$(CONFIG_CPU_S3C2412) += s3c2412.o | ||
38 | obj-$(CONFIG_CPU_S3C2412) += s3c2412-irq.o | ||
39 | obj-$(CONFIG_CPU_S3C2412) += s3c2412-clock.o | ||
40 | obj-dma-$(CONFIG_CPU_S3C2412) += s3c2412-dma.o | ||
41 | |||
42 | obj-$(CONFIG_S3C2412_PM) += s3c2412-pm.o | ||
43 | |||
44 | # | ||
45 | # S3C244X support | ||
46 | |||
47 | obj-$(CONFIG_CPU_S3C244X) += s3c244x.o | ||
48 | obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o | ||
49 | |||
50 | # Clock control | ||
51 | |||
52 | obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o | ||
53 | |||
54 | # S3C2440 support | ||
55 | |||
56 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o | ||
57 | obj-$(CONFIG_CPU_S3C2440) += s3c2440-irq.o | ||
58 | obj-$(CONFIG_CPU_S3C2440) += s3c2440-clock.o | ||
59 | obj-$(CONFIG_CPU_S3C2440) += s3c2410-gpio.o | ||
60 | obj-dma-$(CONFIG_CPU_S3C2440) += s3c2440-dma.o | ||
61 | 19 | ||
62 | # S3C2442 support | 20 | # Machine support |
63 | 21 | ||
64 | obj-$(CONFIG_CPU_S3C2442) += s3c2442.o | 22 | obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o |
65 | obj-$(CONFIG_CPU_S3C2442) += s3c2442-clock.o | ||
66 | |||
67 | # bast extras | ||
68 | |||
69 | obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o | ||
70 | |||
71 | # merge in dma objects | ||
72 | |||
73 | obj-y += $(obj-dma-y) | ||
74 | |||
75 | # machine specific support | ||
76 | |||
77 | obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o | ||
78 | obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o | ||
79 | obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o | ||
80 | obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o | ||
81 | obj-$(CONFIG_ARCH_H1940) += mach-h1940.o | 23 | obj-$(CONFIG_ARCH_H1940) += mach-h1940.o |
24 | obj-$(CONFIG_PM_H1940) += pm-h1940.o | ||
82 | obj-$(CONFIG_MACH_N30) += mach-n30.o | 25 | obj-$(CONFIG_MACH_N30) += mach-n30.o |
83 | obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o | 26 | obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o |
84 | obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o | ||
85 | obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o | ||
86 | obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o | ||
87 | obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o | ||
88 | obj-$(CONFIG_MACH_OTOM) += mach-otom.o | 27 | obj-$(CONFIG_MACH_OTOM) += mach-otom.o |
89 | obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o | 28 | obj-$(CONFIG_MACH_AML_M5900) += mach-amlm5900.o |
90 | obj-$(CONFIG_MACH_VSTMS) += mach-vstms.o | 29 | obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o |
91 | 30 | obj-$(CONFIG_MACH_VR1000) += mach-vr1000.o usb-simtec.o | |
92 | obj-$(CONFIG_MACH_SMDK) += common-smdk.o \ No newline at end of file | 31 | obj-$(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 | |
2 | extern void bast_init_irq(void); | 2 | extern 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 | ||
55 | static LIST_HEAD(clocks); | 48 | int s3c2410_clkcon_enable(struct clk *clk, int enable) |
56 | |||
57 | DEFINE_MUTEX(clocks_mutex); | ||
58 | |||
59 | /* enable and disable calls for use with the clk struct */ | ||
60 | |||
61 | static 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 | ||
68 | struct 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 | ||
107 | void clk_put(struct clk *clk) | 63 | __raw_writel(clkcon, S3C2410_CLKCON); |
108 | { | ||
109 | module_put(clk->owner); | ||
110 | } | ||
111 | 64 | ||
112 | int 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 | ||
128 | void clk_disable(struct clk *clk) | 68 | static 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 | |||
143 | unsigned 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 | |||
160 | long 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 | |||
168 | int 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 | |||
182 | struct 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 | |||
187 | int 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 | |||
204 | EXPORT_SYMBOL(clk_get); | ||
205 | EXPORT_SYMBOL(clk_put); | ||
206 | EXPORT_SYMBOL(clk_enable); | ||
207 | EXPORT_SYMBOL(clk_disable); | ||
208 | EXPORT_SYMBOL(clk_get_rate); | ||
209 | EXPORT_SYMBOL(clk_round_rate); | ||
210 | EXPORT_SYMBOL(clk_set_rate); | ||
211 | EXPORT_SYMBOL(clk_get_parent); | ||
212 | EXPORT_SYMBOL(clk_set_parent); | ||
213 | |||
214 | /* base clocks */ | ||
215 | |||
216 | struct clk clk_xtal = { | ||
217 | .name = "xtal", | ||
218 | .id = -1, | ||
219 | .rate = 0, | ||
220 | .parent = NULL, | ||
221 | .ctrlbit = 0, | ||
222 | }; | ||
223 | |||
224 | struct clk clk_mpll = { | ||
225 | .name = "mpll", | ||
226 | .id = -1, | ||
227 | }; | ||
228 | |||
229 | struct clk clk_upll = { | ||
230 | .name = "upll", | ||
231 | .id = -1, | ||
232 | .parent = NULL, | ||
233 | .ctrlbit = 0, | ||
234 | }; | ||
235 | |||
236 | struct clk clk_f = { | ||
237 | .name = "fclk", | ||
238 | .id = -1, | ||
239 | .rate = 0, | ||
240 | .parent = &clk_mpll, | ||
241 | .ctrlbit = 0, | ||
242 | }; | ||
243 | |||
244 | struct clk clk_h = { | ||
245 | .name = "hclk", | ||
246 | .id = -1, | ||
247 | .rate = 0, | ||
248 | .parent = NULL, | ||
249 | .ctrlbit = 0, | ||
250 | }; | ||
251 | |||
252 | struct clk clk_p = { | ||
253 | .name = "pclk", | ||
254 | .id = -1, | ||
255 | .rate = 0, | ||
256 | .parent = NULL, | ||
257 | .ctrlbit = 0, | ||
258 | }; | ||
259 | |||
260 | struct 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 | |||
269 | static 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 | ||
283 | static 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 */ | |
317 | static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) | 89 | |
318 | { | 90 | static 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 | |||
356 | struct 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 | |||
364 | struct 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 | ||
372 | struct clk s3c24xx_clkout0 = { | 130 | static 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 | ||
378 | struct 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 | |
384 | struct 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 | |||
391 | int 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 | ||
409 | int __init s3c24xx_setup_clocks(unsigned long xtal, | 211 | int __init s3c2410_baseclk_add(void) |
410 | unsigned long fclk, | ||
411 | unsigned long hclk, | ||
412 | unsigned long pclk) | ||
413 | { | 212 | { |
414 | printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n"); | 213 | unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); |
214 | unsigned long clkcon = __raw_readl(S3C2410_CLKCON); | ||
215 | struct clk *clkp; | ||
216 | struct clk *xtal; | ||
217 | int ret; | ||
218 | int ptr; | ||
415 | 219 | ||
416 | /* initialise the main system clocks */ | 220 | clk_upll.enable = s3c2410_upll_enable; |
417 | 221 | ||
418 | clk_xtal.rate = xtal; | 222 | if (s3c24xx_register_clock(&clk_usb_bus) < 0) |
419 | clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal); | 223 | printk(KERN_ERR "failed to register usb bus clock\n"); |
420 | 224 | ||
421 | clk_mpll.rate = fclk; | 225 | /* register clocks from clock array */ |
422 | clk_h.rate = hclk; | ||
423 | clk_p.rate = pclk; | ||
424 | clk_f.rate = fclk; | ||
425 | 226 | ||
426 | /* assume uart clocks are correctly setup */ | 227 | clkp = init_clocks; |
228 | for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { | ||
229 | /* ensure that we note the clock state */ | ||
427 | 230 | ||
428 | /* register our clocks */ | 231 | clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; |
429 | 232 | ||
430 | if (s3c24xx_register_clock(&clk_xtal) < 0) | 233 | ret = s3c24xx_register_clock(clkp); |
431 | printk(KERN_ERR "failed to register master xtal\n"); | 234 | if (ret < 0) { |
235 | printk(KERN_ERR "Failed to register clock %s (%d)\n", | ||
236 | clkp->name, ret); | ||
237 | } | ||
238 | } | ||
432 | 239 | ||
433 | if (s3c24xx_register_clock(&clk_mpll) < 0) | 240 | /* We must be careful disabling the clocks we are not intending to |
434 | printk(KERN_ERR "failed to register mpll clock\n"); | 241 | * be using at boot time, as subsytems such as the LCD which do |
242 | * their own DMA requests to the bus can cause the system to lockup | ||
243 | * if they where in the middle of requesting bus access. | ||
244 | * | ||
245 | * Disabling the LCD clock if the LCD is active is very dangerous, | ||
246 | * and therefore the bootloader should be careful to not enable | ||
247 | * the LCD clock if it is not needed. | ||
248 | */ | ||
249 | |||
250 | /* install (and disable) the clocks we do not need immediately */ | ||
251 | |||
252 | clkp = init_clocks_disable; | ||
253 | for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { | ||
254 | |||
255 | ret = s3c24xx_register_clock(clkp); | ||
256 | if (ret < 0) { | ||
257 | printk(KERN_ERR "Failed to register clock %s (%d)\n", | ||
258 | clkp->name, ret); | ||
259 | } | ||
435 | 260 | ||
436 | if (s3c24xx_register_clock(&clk_upll) < 0) | 261 | s3c2410_clkcon_enable(clkp, 0); |
437 | printk(KERN_ERR "failed to register upll clock\n"); | 262 | } |
438 | 263 | ||
439 | if (s3c24xx_register_clock(&clk_f) < 0) | 264 | /* show the clock-slow value */ |
440 | printk(KERN_ERR "failed to register cpu fclk\n"); | ||
441 | 265 | ||
442 | if (s3c24xx_register_clock(&clk_h) < 0) | 266 | xtal = clk_get(NULL, "xtal"); |
443 | printk(KERN_ERR "failed to register cpu hclk\n"); | ||
444 | 267 | ||
445 | if (s3c24xx_register_clock(&clk_p) < 0) | 268 | printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", |
446 | printk(KERN_ERR "failed to register cpu pclk\n"); | 269 | print_mhz(clk_get_rate(xtal) / |
270 | ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), | ||
271 | (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", | ||
272 | (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", | ||
273 | (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); | ||
447 | 274 | ||
448 | return 0; | 275 | return 0; |
449 | } | 276 | } |
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h deleted file mode 100644 index 7f0ea03e1d49..000000000000 --- a/arch/arm/mach-s3c2410/clock.h +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-s3c2410/clock.h | ||
3 | * | ||
4 | * Copyright (c) 2004-2005 Simtec Electronics | ||
5 | * http://www.simtec.co.uk/products/SWLINUX/ | ||
6 | * Written by Ben Dooks, <ben@simtec.co.uk> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | struct clk { | ||
14 | struct list_head list; | ||
15 | struct module *owner; | ||
16 | struct clk *parent; | ||
17 | const char *name; | ||
18 | int id; | ||
19 | int usage; | ||
20 | unsigned long rate; | ||
21 | unsigned long ctrlbit; | ||
22 | |||
23 | int (*enable)(struct clk *, int enable); | ||
24 | int (*set_rate)(struct clk *c, unsigned long rate); | ||
25 | unsigned long (*get_rate)(struct clk *c); | ||
26 | unsigned long (*round_rate)(struct clk *c, unsigned long rate); | ||
27 | int (*set_parent)(struct clk *c, struct clk *parent); | ||
28 | }; | ||
29 | |||
30 | /* other clocks which may be registered by board support */ | ||
31 | |||
32 | extern struct clk s3c24xx_dclk0; | ||
33 | extern struct clk s3c24xx_dclk1; | ||
34 | extern struct clk s3c24xx_clkout0; | ||
35 | extern struct clk s3c24xx_clkout1; | ||
36 | extern struct clk s3c24xx_uclk; | ||
37 | |||
38 | extern struct clk clk_usb_bus; | ||
39 | |||
40 | /* core clock support */ | ||
41 | |||
42 | extern struct clk clk_f; | ||
43 | extern struct clk clk_h; | ||
44 | extern struct clk clk_p; | ||
45 | extern struct clk clk_mpll; | ||
46 | extern struct clk clk_upll; | ||
47 | extern struct clk clk_xtal; | ||
48 | |||
49 | /* exports for arch/arm/mach-s3c2410 | ||
50 | * | ||
51 | * Please DO NOT use these outside of arch/arm/mach-s3c2410 | ||
52 | */ | ||
53 | |||
54 | extern struct mutex clocks_mutex; | ||
55 | |||
56 | extern int s3c2410_clkcon_enable(struct clk *clk, int enable); | ||
57 | |||
58 | extern int s3c24xx_register_clock(struct clk *clk); | ||
59 | |||
60 | extern int s3c24xx_setup_clocks(unsigned long xtal, | ||
61 | unsigned long fclk, | ||
62 | unsigned long hclk, | ||
63 | unsigned long pclk); | ||
diff --git a/arch/arm/mach-s3c2410/common-smdk.h b/arch/arm/mach-s3c2410/common-smdk.h deleted file mode 100644 index 0e3a3be330a3..000000000000 --- a/arch/arm/mach-s3c2410/common-smdk.h +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/common-smdk.h | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Common code for SMDK2410 and SMDK2440 boards | ||
7 | * | ||
8 | * http://www.fluff.org/ben/smdk2440/ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | extern void smdk_machine_init(void); | ||
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h deleted file mode 100644 index be42e4032a6d..000000000000 --- a/arch/arm/mach-s3c2410/cpu.h +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/cpu.h | ||
2 | * | ||
3 | * Copyright (c) 2004-2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for S3C24XX CPU support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | /* todo - fix when rmk changes iodescs to use `void __iomem *` */ | ||
14 | |||
15 | #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } | ||
16 | |||
17 | #ifndef MHZ | ||
18 | #define MHZ (1000*1000) | ||
19 | #endif | ||
20 | |||
21 | #define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000) | ||
22 | |||
23 | /* forward declaration */ | ||
24 | struct s3c24xx_uart_resources; | ||
25 | struct platform_device; | ||
26 | struct s3c2410_uartcfg; | ||
27 | struct map_desc; | ||
28 | |||
29 | /* core initialisation functions */ | ||
30 | |||
31 | extern void s3c24xx_init_irq(void); | ||
32 | |||
33 | extern void s3c24xx_init_io(struct map_desc *mach_desc, int size); | ||
34 | |||
35 | extern void s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
36 | |||
37 | extern void s3c24xx_init_clocks(int xtal); | ||
38 | |||
39 | extern void s3c24xx_init_uartdevs(char *name, | ||
40 | struct s3c24xx_uart_resources *res, | ||
41 | struct s3c2410_uartcfg *cfg, int no); | ||
42 | |||
43 | /* the board structure is used at first initialsation time | ||
44 | * to get info such as the devices to register for this | ||
45 | * board. This is done because platfrom_add_devices() cannot | ||
46 | * be called from the map_io entry. | ||
47 | */ | ||
48 | |||
49 | struct s3c24xx_board { | ||
50 | struct platform_device **devices; | ||
51 | unsigned int devices_count; | ||
52 | |||
53 | struct clk **clocks; | ||
54 | unsigned int clocks_count; | ||
55 | }; | ||
56 | |||
57 | extern void s3c24xx_set_board(struct s3c24xx_board *board); | ||
58 | |||
59 | /* timer for 2410/2440 */ | ||
60 | |||
61 | struct sys_timer; | ||
62 | extern struct sys_timer s3c24xx_timer; | ||
63 | |||
64 | /* system device classes */ | ||
65 | |||
66 | extern struct sysdev_class s3c2410_sysclass; | ||
67 | extern struct sysdev_class s3c2412_sysclass; | ||
68 | extern struct sysdev_class s3c2440_sysclass; | ||
69 | extern struct sysdev_class s3c2442_sysclass; | ||
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h deleted file mode 100644 index 14fb0bade716..000000000000 --- a/arch/arm/mach-s3c2410/devs.h +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/devs.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for s3c2410 standard platform devices | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | struct s3c24xx_uart_resources { | ||
15 | struct resource *resources; | ||
16 | unsigned long nr_resources; | ||
17 | }; | ||
18 | |||
19 | extern struct s3c24xx_uart_resources s3c2410_uart_resources[]; | ||
20 | |||
21 | extern struct platform_device *s3c24xx_uart_devs[]; | ||
22 | extern struct platform_device *s3c24xx_uart_src[]; | ||
23 | |||
24 | extern struct platform_device s3c_device_usb; | ||
25 | extern struct platform_device s3c_device_lcd; | ||
26 | extern struct platform_device s3c_device_wdt; | ||
27 | extern struct platform_device s3c_device_i2c; | ||
28 | extern struct platform_device s3c_device_iis; | ||
29 | extern struct platform_device s3c_device_rtc; | ||
30 | extern struct platform_device s3c_device_adc; | ||
31 | extern struct platform_device s3c_device_sdi; | ||
32 | |||
33 | extern struct platform_device s3c_device_spi0; | ||
34 | extern struct platform_device s3c_device_spi1; | ||
35 | |||
36 | extern struct platform_device s3c_device_nand; | ||
37 | |||
38 | extern struct platform_device s3c_device_timer0; | ||
39 | extern struct platform_device s3c_device_timer1; | ||
40 | extern struct platform_device s3c_device_timer2; | ||
41 | extern struct platform_device s3c_device_timer3; | ||
42 | |||
43 | extern struct platform_device s3c_device_usbgadget; | ||
44 | |||
45 | /* s3c2440 specific devices */ | ||
46 | |||
47 | #ifdef CONFIG_CPU_S3C2440 | ||
48 | |||
49 | extern struct platform_device s3c_device_camif; | ||
50 | |||
51 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index fa860e716b4f..67d1ad363973 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/dma.c | 1 | /* linux/arch/arm/mach-s3c2410/dma.c |
2 | * | 2 | * |
3 | * Copyright (c) 2003-2005,2006 Simtec Electronics | 3 | * Copyright (c) 2006 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 4 | * Ben Dooks <ben@simtec.co.uk> |
5 | * | 5 | * |
6 | * S3C2410 DMA core | 6 | * S3C2410 DMA selection |
7 | * | 7 | * |
8 | * http://armlinux.simtec.co.uk/ | 8 | * http://armlinux.simtec.co.uk/ |
9 | * | 9 | * |
@@ -12,1430 +12,170 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | 15 | #include <linux/kernel.h> | |
16 | #ifdef CONFIG_S3C2410_DMA_DEBUG | ||
17 | #define DEBUG | ||
18 | #endif | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | 16 | #include <linux/init.h> |
22 | #include <linux/sched.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/sysdev.h> | 17 | #include <linux/sysdev.h> |
26 | #include <linux/slab.h> | 18 | #include <linux/serial_core.h> |
27 | #include <linux/errno.h> | ||
28 | #include <linux/delay.h> | ||
29 | 19 | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/irq.h> | ||
32 | #include <asm/hardware.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/dma.h> | 20 | #include <asm/dma.h> |
35 | 21 | #include <asm/arch/dma.h> | |
36 | #include <asm/mach/dma.h> | 22 | |
37 | #include <asm/arch/map.h> | 23 | #include <asm/plat-s3c24xx/cpu.h> |
38 | 24 | #include <asm/plat-s3c24xx/dma.h> | |
39 | #include "dma.h" | 25 | |
40 | 26 | #include <asm/arch/regs-serial.h> | |
41 | /* io map for dma */ | 27 | #include <asm/arch/regs-gpio.h> |
42 | static void __iomem *dma_base; | 28 | #include <asm/arch/regs-ac97.h> |
43 | static struct kmem_cache *dma_kmem; | 29 | #include <asm/arch/regs-mem.h> |
44 | 30 | #include <asm/arch/regs-lcd.h> | |
45 | struct 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> |
48 | struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; | 34 | |
49 | 35 | static 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, |
61 | static inline void | 47 | .channels[2] = S3C2410_DCON_CH2_SDI | DMA_CH_VALID, |
62 | dma_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] = { | |
73 | struct 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 | 117 | static 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 | |||
88 | static void | ||
89 | dmadbg_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 | |||
98 | static void | ||
99 | dmadbg_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 | |||
108 | static void | ||
109 | dmadbg_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 | |||
122 | static void | ||
123 | dmadbg_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 | |||
138 | static 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 | |||
145 | static 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 | |||
158 | static void | ||
159 | s3c2410_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 | 123 | static 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), | |
177 | static int | 128 | }; |
178 | s3c2410_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 | |||
224 | static inline int | ||
225 | s3c2410_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 | |||
298 | static void | ||
299 | s3c2410_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 | |||
312 | static inline void | ||
313 | s3c2410_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 | |||
331 | static 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 | |||
426 | static int | ||
427 | s3c2410_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 | |||
453 | int 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 | |||
534 | EXPORT_SYMBOL(s3c2410_dma_enqueue); | ||
535 | |||
536 | static inline void | ||
537 | s3c2410_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 | |||
556 | static inline void | ||
557 | s3c2410_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 | |||
597 | static irqreturn_t | ||
598 | s3c2410_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 | |||
726 | static 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 | |||
733 | int 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 | |||
791 | EXPORT_SYMBOL(s3c2410_dma_request); | ||
792 | 129 | ||
793 | /* s3c2410_dma_free | 130 | static 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 | ||
804 | int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client) | 148 | static 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 | ||
845 | EXPORT_SYMBOL(s3c2410_dma_free); | 155 | #if defined(CONFIG_CPU_S3C2410) |
846 | 156 | static struct sysdev_driver s3c2410_dma_driver = { | |
847 | static 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 | ||
881 | void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan) | 160 | static 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 | 165 | arch_initcall(s3c2410_dma_drvinit); | |
897 | /* s3c2410_dma_flush | ||
898 | * | ||
899 | * stop the channel, and remove all current and pending transfers | ||
900 | */ | ||
901 | |||
902 | static 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); | 170 | static struct sysdev_driver s3c2442_dma_driver = { |
954 | 171 | .add = s3c2410_dma_add, | |
955 | return 0; | ||
956 | } | ||
957 | |||
958 | int | ||
959 | s3c2410_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 | |||
995 | int | ||
996 | s3c2410_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 | |||
1028 | EXPORT_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 | |||
1044 | int 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 | |||
1091 | EXPORT_SYMBOL(s3c2410_dma_config); | ||
1092 | |||
1093 | int 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 | |||
1107 | EXPORT_SYMBOL(s3c2410_dma_setflags); | ||
1108 | |||
1109 | |||
1110 | /* do we need to protect the settings of the fields from | ||
1111 | * irq? | ||
1112 | */ | ||
1113 | |||
1114 | int 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 | |||
1128 | EXPORT_SYMBOL(s3c2410_dma_set_opfn); | ||
1129 | |||
1130 | int 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 | |||
1144 | EXPORT_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 | |||
1160 | int 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 | |||
1204 | EXPORT_SYMBOL(s3c2410_dma_devconfig); | ||
1205 | |||
1206 | /* s3c2410_dma_getposition | ||
1207 | * | ||
1208 | * returns the current transfer points for the dma source and destination | ||
1209 | */ | ||
1210 | |||
1211 | int 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 | |||
1227 | EXPORT_SYMBOL(s3c2410_dma_getposition); | ||
1228 | |||
1229 | |||
1230 | /* system device class */ | ||
1231 | |||
1232 | #ifdef CONFIG_PM | ||
1233 | |||
1234 | static 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 | |||
1256 | static 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 | |||
1266 | struct 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 */ | 174 | static int __init s3c2442_dma_drvinit(void) |
1273 | |||
1274 | static 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 | |||
1281 | static 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 | |||
1350 | core_initcall(s3c2410_init_dma); | ||
1351 | |||
1352 | static 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() | 179 | arch_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 | |||
1367 | struct 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 | |||
1403 | static 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 | |||
1414 | static 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 | |||
1422 | int __init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel) | ||
1423 | { | ||
1424 | struct s3c24xx_dma_map *nmap; | ||
1425 | size_t map_sz = sizeof(*nmap) * sel->map_size; | ||
1426 | int ptr; | ||
1427 | |||
1428 | nmap = kmalloc(map_sz, GFP_KERNEL); | ||
1429 | if (nmap == NULL) | ||
1430 | return -ENOMEM; | ||
1431 | |||
1432 | memcpy(nmap, sel->map, map_sz); | ||
1433 | memcpy(&dma_sel, sel, sizeof(*sel)); | ||
1434 | |||
1435 | dma_sel.map = nmap; | ||
1436 | |||
1437 | for (ptr = 0; ptr < sel->map_size; ptr++) | ||
1438 | s3c24xx_dma_check_entry(nmap+ptr, ptr); | ||
1439 | 181 | ||
1440 | return 0; | ||
1441 | } | ||
diff --git a/arch/arm/mach-s3c2410/dma.h b/arch/arm/mach-s3c2410/dma.h deleted file mode 100644 index 0ebfe0aab80b..000000000000 --- a/arch/arm/mach-s3c2410/dma.h +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/dma.h | ||
2 | * | ||
3 | * Copyright (C) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Samsung S3C24XX DMA support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | extern struct sysdev_class dma_sysclass; | ||
14 | extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS]; | ||
15 | |||
16 | #define DMA_CH_VALID (1<<31) | ||
17 | |||
18 | struct s3c24xx_dma_addr { | ||
19 | unsigned long from; | ||
20 | unsigned long to; | ||
21 | }; | ||
22 | |||
23 | /* struct s3c24xx_dma_map | ||
24 | * | ||
25 | * this holds the mapping information for the channel selected | ||
26 | * to be connected to the specified device | ||
27 | */ | ||
28 | |||
29 | struct s3c24xx_dma_map { | ||
30 | const char *name; | ||
31 | struct s3c24xx_dma_addr hw_addr; | ||
32 | |||
33 | unsigned long channels[S3C2410_DMA_CHANNELS]; | ||
34 | }; | ||
35 | |||
36 | struct s3c24xx_dma_selection { | ||
37 | struct s3c24xx_dma_map *map; | ||
38 | unsigned long map_size; | ||
39 | unsigned long dcon_mask; | ||
40 | |||
41 | void (*select)(struct s3c2410_dma_chan *chan, | ||
42 | struct s3c24xx_dma_map *map); | ||
43 | }; | ||
44 | |||
45 | extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel); | ||
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c index f6fb215bb48c..01e795d1146e 100644 --- a/arch/arm/mach-s3c2410/gpio.c +++ b/arch/arm/mach-s3c2410/gpio.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/gpio.c | 1 | /* linux/arch/arm/mach-s3c2410/gpio.c |
2 | * | 2 | * |
3 | * Copyright (c) 2004-2005 Simtec Electronics | 3 | * Copyright (c) 2004-2006 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 4 | * Ben Dooks <ben@simtec.co.uk> |
5 | * | 5 | * |
6 | * S3C24XX GPIO support | 6 | * S3C2410 GPIO support |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -18,8 +18,7 @@ | |||
18 | * You should have received a copy of the GNU General Public License | 18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software | 19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 | */ | 21 | */ |
22 | |||
23 | 22 | ||
24 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
25 | #include <linux/init.h> | 24 | #include <linux/init.h> |
@@ -33,156 +32,40 @@ | |||
33 | 32 | ||
34 | #include <asm/arch/regs-gpio.h> | 33 | #include <asm/arch/regs-gpio.h> |
35 | 34 | ||
36 | void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) | 35 | int 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 | |||
82 | EXPORT_SYMBOL(s3c2410_gpio_cfgpin); | ||
83 | |||
84 | unsigned 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 | |||
101 | EXPORT_SYMBOL(s3c2410_gpio_getcfg); | ||
102 | |||
103 | void 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 | ||
123 | EXPORT_SYMBOL(s3c2410_gpio_pullup); | 45 | config &= 0xff; |
124 | 46 | ||
125 | void 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 | |||
142 | EXPORT_SYMBOL(s3c2410_gpio_setpin); | ||
143 | |||
144 | unsigned 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 | ||
152 | EXPORT_SYMBOL(s3c2410_gpio_getpin); | 59 | /* update filter enable */ |
153 | 60 | ||
154 | unsigned 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 | |||
169 | EXPORT_SYMBOL(s3c2410_modify_misccr); | ||
170 | |||
171 | int 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 | ||
188 | EXPORT_SYMBOL(s3c2410_gpio_getirq); | 71 | EXPORT_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 | |||
84 | unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL; | ||
85 | unsigned long s3c_irqwake_intmask = 0xffffffffL; | ||
86 | unsigned long s3c_irqwake_eintallow = 0x0000fff0L; | ||
87 | unsigned long s3c_irqwake_eintmask = 0xffffffffL; | ||
88 | |||
89 | int | ||
90 | s3c_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 | |||
108 | static int | ||
109 | s3c_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 | |||
133 | static void | ||
134 | s3c_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 | |||
145 | static inline void | ||
146 | s3c_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 | |||
154 | static inline void | ||
155 | s3c_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 | |||
168 | static void | ||
169 | s3c_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 | |||
183 | struct 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 | |||
191 | static 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 | |||
199 | static void | ||
200 | s3c_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 | |||
211 | static void | ||
212 | s3c_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); | 32 | static 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 | |||
238 | static void | ||
239 | s3c_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 | |||
250 | int | ||
251 | s3c_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 | ||
332 | static struct irq_chip s3c_irqext_chip = { | 37 | static 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 | |||
341 | static 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 | |||
360 | static void | ||
361 | s3c_irq_uart0_mask(unsigned int irqno) | ||
362 | { | ||
363 | s3c_irqsub_mask(irqno, INTMSK_UART0, 7); | ||
364 | } | ||
365 | |||
366 | static void | ||
367 | s3c_irq_uart0_unmask(unsigned int irqno) | ||
368 | { | ||
369 | s3c_irqsub_unmask(irqno, INTMSK_UART0); | ||
370 | } | ||
371 | |||
372 | static void | ||
373 | s3c_irq_uart0_ack(unsigned int irqno) | ||
374 | { | ||
375 | s3c_irqsub_maskack(irqno, INTMSK_UART0, 7); | ||
376 | } | ||
377 | |||
378 | static 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 | |||
387 | static void | ||
388 | s3c_irq_uart1_mask(unsigned int irqno) | ||
389 | { | ||
390 | s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3); | ||
391 | } | ||
392 | |||
393 | static void | ||
394 | s3c_irq_uart1_unmask(unsigned int irqno) | ||
395 | { | ||
396 | s3c_irqsub_unmask(irqno, INTMSK_UART1); | ||
397 | } | ||
398 | |||
399 | static void | ||
400 | s3c_irq_uart1_ack(unsigned int irqno) | ||
401 | { | ||
402 | s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3); | ||
403 | } | ||
404 | |||
405 | static 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 | |||
414 | static void | ||
415 | s3c_irq_uart2_mask(unsigned int irqno) | ||
416 | { | ||
417 | s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6); | ||
418 | } | ||
419 | |||
420 | static void | ||
421 | s3c_irq_uart2_unmask(unsigned int irqno) | ||
422 | { | ||
423 | s3c_irqsub_unmask(irqno, INTMSK_UART2); | ||
424 | } | ||
425 | |||
426 | static void | ||
427 | s3c_irq_uart2_ack(unsigned int irqno) | ||
428 | { | ||
429 | s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6); | ||
430 | } | ||
431 | |||
432 | static 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 | |||
441 | static void | ||
442 | s3c_irq_adc_mask(unsigned int irqno) | ||
443 | { | ||
444 | s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9); | ||
445 | } | ||
446 | |||
447 | static void | ||
448 | s3c_irq_adc_unmask(unsigned int irqno) | ||
449 | { | ||
450 | s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT); | ||
451 | } | ||
452 | |||
453 | static void | ||
454 | s3c_irq_adc_ack(unsigned int irqno) | ||
455 | { | ||
456 | s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9); | ||
457 | } | ||
458 | |||
459 | static 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 */ | ||
467 | static 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 | |||
496 | static 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 | |||
535 | static void | ||
536 | s3c_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 | |||
543 | static void | ||
544 | s3c_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 | |||
551 | static void | ||
552 | s3c_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 | |||
559 | static void | ||
560 | s3c_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 | |||
581 | static void | ||
582 | s3c_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 | |||
605 | static 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 | 43 | static 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 | |||
615 | static unsigned long save_extint[3]; | ||
616 | static unsigned long save_eintflt[4]; | ||
617 | static unsigned long save_eintmask; | ||
618 | |||
619 | int 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 | ||
635 | int s3c24xx_irq_resume(struct sys_device *dev) | 48 | arch_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 | |||
661 | void __init s3c24xx_init_irq(void) | ||
662 | { | ||
663 | unsigned long pend; | ||
664 | unsigned long last; | ||
665 | int irqno; | ||
666 | int i; | ||
667 | |||
668 | irqdbf("s3c2410_init_irq: clearing interrupt status flags\n"); | ||
669 | |||
670 | /* first, clear all interrupts pending... */ | ||
671 | |||
672 | last = 0; | ||
673 | for (i = 0; i < 4; i++) { | ||
674 | pend = __raw_readl(S3C24XX_EINTPEND); | ||
675 | |||
676 | if (pend == 0 || pend == last) | ||
677 | break; | ||
678 | |||
679 | __raw_writel(pend, S3C24XX_EINTPEND); | ||
680 | printk("irq: clearing pending ext status %08x\n", (int)pend); | ||
681 | last = pend; | ||
682 | } | ||
683 | |||
684 | last = 0; | ||
685 | for (i = 0; i < 4; i++) { | ||
686 | pend = __raw_readl(S3C2410_INTPND); | ||
687 | |||
688 | if (pend == 0 || pend == last) | ||
689 | break; | ||
690 | |||
691 | __raw_writel(pend, S3C2410_SRCPND); | ||
692 | __raw_writel(pend, S3C2410_INTPND); | ||
693 | printk("irq: clearing pending status %08x\n", (int)pend); | ||
694 | last = pend; | ||
695 | } | ||
696 | |||
697 | last = 0; | ||
698 | for (i = 0; i < 4; i++) { | ||
699 | pend = __raw_readl(S3C2410_SUBSRCPND); | ||
700 | |||
701 | if (pend == 0 || pend == last) | ||
702 | break; | ||
703 | |||
704 | printk("irq: clearing subpending status %08x\n", (int)pend); | ||
705 | __raw_writel(pend, S3C2410_SUBSRCPND); | ||
706 | last = pend; | ||
707 | } | ||
708 | |||
709 | /* register the main interrupts */ | ||
710 | |||
711 | irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); | ||
712 | |||
713 | for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) { | ||
714 | /* set all the s3c2410 internal irqs */ | ||
715 | |||
716 | switch (irqno) { | ||
717 | /* deal with the special IRQs (cascaded) */ | ||
718 | |||
719 | case IRQ_EINT4t7: | ||
720 | case IRQ_EINT8t23: | ||
721 | case IRQ_UART0: | ||
722 | case IRQ_UART1: | ||
723 | case IRQ_UART2: | ||
724 | case IRQ_ADCPARENT: | ||
725 | set_irq_chip(irqno, &s3c_irq_level_chip); | ||
726 | set_irq_handler(irqno, handle_level_irq); | ||
727 | break; | ||
728 | |||
729 | case IRQ_RESERVED6: | ||
730 | case IRQ_RESERVED24: | ||
731 | /* no IRQ here */ | ||
732 | break; | ||
733 | |||
734 | default: | ||
735 | //irqdbf("registering irq %d (s3c irq)\n", irqno); | ||
736 | set_irq_chip(irqno, &s3c_irq_chip); | ||
737 | set_irq_handler(irqno, handle_edge_irq); | ||
738 | set_irq_flags(irqno, IRQF_VALID); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | /* setup the cascade irq handlers */ | ||
743 | |||
744 | set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7); | ||
745 | set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8); | ||
746 | |||
747 | set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); | ||
748 | set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); | ||
749 | set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); | ||
750 | set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); | ||
751 | |||
752 | /* external interrupts */ | ||
753 | |||
754 | for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { | ||
755 | irqdbf("registering irq %d (ext int)\n", irqno); | ||
756 | set_irq_chip(irqno, &s3c_irq_eint0t4); | ||
757 | set_irq_handler(irqno, handle_edge_irq); | ||
758 | set_irq_flags(irqno, IRQF_VALID); | ||
759 | } | ||
760 | |||
761 | for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { | ||
762 | irqdbf("registering irq %d (extended s3c irq)\n", irqno); | ||
763 | set_irq_chip(irqno, &s3c_irqext_chip); | ||
764 | set_irq_handler(irqno, handle_edge_irq); | ||
765 | set_irq_flags(irqno, IRQF_VALID); | ||
766 | } | ||
767 | |||
768 | /* register the uart interrupts */ | ||
769 | |||
770 | irqdbf("s3c2410: registering external interrupts\n"); | ||
771 | |||
772 | for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { | ||
773 | irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); | ||
774 | set_irq_chip(irqno, &s3c_irq_uart0); | ||
775 | set_irq_handler(irqno, handle_level_irq); | ||
776 | set_irq_flags(irqno, IRQF_VALID); | ||
777 | } | ||
778 | |||
779 | for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { | ||
780 | irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); | ||
781 | set_irq_chip(irqno, &s3c_irq_uart1); | ||
782 | set_irq_handler(irqno, handle_level_irq); | ||
783 | set_irq_flags(irqno, IRQF_VALID); | ||
784 | } | ||
785 | |||
786 | for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { | ||
787 | irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); | ||
788 | set_irq_chip(irqno, &s3c_irq_uart2); | ||
789 | set_irq_handler(irqno, handle_level_irq); | ||
790 | set_irq_flags(irqno, IRQF_VALID); | ||
791 | } | ||
792 | |||
793 | for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { | ||
794 | irqdbf("registering irq %d (s3c adc irq)\n", irqno); | ||
795 | set_irq_chip(irqno, &s3c_irq_adc); | ||
796 | set_irq_handler(irqno, handle_edge_irq); | ||
797 | set_irq_flags(irqno, IRQF_VALID); | ||
798 | } | ||
799 | |||
800 | irqdbf("s3c2410: registered interrupt handlers\n"); | ||
801 | } | ||
diff --git a/arch/arm/mach-s3c2410/irq.h b/arch/arm/mach-s3c2410/irq.h deleted file mode 100644 index e5913da3b919..000000000000 --- a/arch/arm/mach-s3c2410/irq.h +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/irq.h | ||
2 | * | ||
3 | * Copyright (c) 2004-2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for S3C24XX CPU IRQ support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #define irqdbf(x...) | ||
14 | #define irqdbf2(x...) | ||
15 | |||
16 | #define EXTINT_OFF (IRQ_EINT4 - 4) | ||
17 | |||
18 | extern struct irq_chip s3c_irq_level_chip; | ||
19 | |||
20 | static inline void | ||
21 | s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit, | ||
22 | int subcheck) | ||
23 | { | ||
24 | unsigned long mask; | ||
25 | unsigned long submask; | ||
26 | |||
27 | submask = __raw_readl(S3C2410_INTSUBMSK); | ||
28 | mask = __raw_readl(S3C2410_INTMSK); | ||
29 | |||
30 | submask |= (1UL << (irqno - IRQ_S3CUART_RX0)); | ||
31 | |||
32 | /* check to see if we need to mask the parent IRQ */ | ||
33 | |||
34 | if ((submask & subcheck) == subcheck) { | ||
35 | __raw_writel(mask | parentbit, S3C2410_INTMSK); | ||
36 | } | ||
37 | |||
38 | /* write back masks */ | ||
39 | __raw_writel(submask, S3C2410_INTSUBMSK); | ||
40 | |||
41 | } | ||
42 | |||
43 | static inline void | ||
44 | s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit) | ||
45 | { | ||
46 | unsigned long mask; | ||
47 | unsigned long submask; | ||
48 | |||
49 | submask = __raw_readl(S3C2410_INTSUBMSK); | ||
50 | mask = __raw_readl(S3C2410_INTMSK); | ||
51 | |||
52 | submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0)); | ||
53 | mask &= ~parentbit; | ||
54 | |||
55 | /* write back masks */ | ||
56 | __raw_writel(submask, S3C2410_INTSUBMSK); | ||
57 | __raw_writel(mask, S3C2410_INTMSK); | ||
58 | } | ||
59 | |||
60 | |||
61 | static inline void | ||
62 | s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group) | ||
63 | { | ||
64 | unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0); | ||
65 | |||
66 | s3c_irqsub_mask(irqno, parentmask, group); | ||
67 | |||
68 | __raw_writel(bit, S3C2410_SUBSRCPND); | ||
69 | |||
70 | /* only ack parent if we've got all the irqs (seems we must | ||
71 | * ack, all and hope that the irq system retriggers ok when | ||
72 | * the interrupt goes off again) | ||
73 | */ | ||
74 | |||
75 | if (1) { | ||
76 | __raw_writel(parentmask, S3C2410_SRCPND); | ||
77 | __raw_writel(parentmask, S3C2410_INTPND); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static inline void | ||
82 | s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group) | ||
83 | { | ||
84 | unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0); | ||
85 | |||
86 | __raw_writel(bit, S3C2410_SUBSRCPND); | ||
87 | |||
88 | /* only ack parent if we've got all the irqs (seems we must | ||
89 | * ack, all and hope that the irq system retriggers ok when | ||
90 | * the interrupt goes off again) | ||
91 | */ | ||
92 | |||
93 | if (1) { | ||
94 | __raw_writel(parentmask, S3C2410_SRCPND); | ||
95 | __raw_writel(parentmask, S3C2410_INTPND); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /* exported for use in arch/arm/mach-s3c2410 */ | ||
100 | |||
101 | #ifdef CONFIG_PM | ||
102 | extern int s3c_irq_wake(unsigned int irqno, unsigned int state); | ||
103 | #else | ||
104 | #define s3c_irq_wake NULL | ||
105 | #endif | ||
106 | |||
107 | extern int s3c_irqext_type(unsigned int irq, unsigned int type); | ||
diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c index 817e2c684410..72f2cc4fcd03 100644 --- a/arch/arm/mach-s3c2410/mach-amlm5900.c +++ b/arch/arm/mach-s3c2410/mach-amlm5900.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /*********************************************************************** | 1 | /* linux/arch/arm/mach-s3c2410/mach-amlm5900.c |
2 | * | 2 | * |
3 | * linux/arch/arm/mach-s3c2410/mach-amlm5900.c | 3 | * linux/arch/arm/mach-s3c2410/mach-amlm5900.c |
4 | * | 4 | * |
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/device.h> | 35 | #include <linux/device.h> |
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | 38 | #include <linux/serial_core.h> | |
39 | 39 | ||
40 | #include <asm/mach/arch.h> | 40 | #include <asm/mach/arch.h> |
41 | #include <asm/mach/map.h> | 41 | #include <asm/mach/map.h> |
@@ -52,8 +52,8 @@ | |||
52 | #include <asm/arch/regs-lcd.h> | 52 | #include <asm/arch/regs-lcd.h> |
53 | #include <asm/arch/regs-gpio.h> | 53 | #include <asm/arch/regs-gpio.h> |
54 | 54 | ||
55 | #include "devs.h" | 55 | #include <asm/plat-s3c24xx/devs.h> |
56 | #include "cpu.h" | 56 | #include <asm/plat-s3c24xx/cpu.h> |
57 | 57 | ||
58 | #ifdef CONFIG_MTD_PARTITIONS | 58 | #ifdef CONFIG_MTD_PARTITIONS |
59 | 59 | ||
@@ -113,12 +113,6 @@ static struct platform_device amlm5900_device_nor = { | |||
113 | #endif | 113 | #endif |
114 | 114 | ||
115 | static struct map_desc amlm5900_iodesc[] __initdata = { | 115 | static 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 | ||
46 | static struct map_desc h1940_iodesc[] __initdata = { | 47 | static 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 | ||
103 | EXPORT_SYMBOL_GPL(h1940_latch_control); | 104 | EXPORT_SYMBOL_GPL(h1940_latch_control); |
104 | 105 | ||
106 | static 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 | |||
125 | static 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 | ||
176 | static struct platform_device s3c_device_leds = { | ||
177 | .name = "h1940-leds", | ||
178 | .id = -1, | ||
179 | }; | ||
180 | |||
149 | static struct platform_device *h1940_devices[] __initdata = { | 181 | static 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 | ||
157 | static struct s3c24xx_board h1940_board __initdata = { | 191 | static struct s3c24xx_board h1940_board __initdata = { |
@@ -179,7 +213,23 @@ static void __init h1940_init_irq(void) | |||
179 | 213 | ||
180 | static void __init h1940_init(void) | 214 | static 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 | ||
185 | MACHINE_START(H1940, "IPAQ-H1940") | 235 | MACHINE_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, |
194 | MACHINE_END | 244 | MACHINE_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 | ||
46 | static struct map_desc n30_iodesc[] __initdata = { | 45 | static 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 | ||
40 | static struct map_desc otom11_iodesc[] __initdata = { | 40 | static 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 | |||
64 | static 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 | |||
72 | static 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 */ | ||
99 | static 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 */ | ||
150 | static 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 */ | ||
201 | static 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 | |||
253 | static 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 | |||
266 | static 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 | |||
274 | static 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 | |||
281 | static 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 | |||
291 | static 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 | |||
303 | static 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 | |||
311 | static 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 | |||
321 | static 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 | |||
334 | static struct s3c24xx_board qt2410_board __initdata = { | ||
335 | .devices = qt2410_devices, | ||
336 | .devices_count = ARRAY_SIZE(qt2410_devices) | ||
337 | }; | ||
338 | |||
339 | static 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 | |||
367 | static 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 | |||
380 | static 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 | |||
390 | static struct s3c2410_udc_mach_info qt2410_udc_cfg = { | ||
391 | }; | ||
392 | |||
393 | static char tft_type = 's'; | ||
394 | |||
395 | static 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 | |||
403 | static 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 | |||
411 | static 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 | |||
438 | MACHINE_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, | ||
446 | MACHINE_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 | ||
57 | static struct map_desc smdk2410_iodesc[] __initdata = { | 57 | static 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 | |||
55 | unsigned long s3c_pm_flags; | ||
56 | |||
57 | #define PFX "s3c24xx-pm: " | ||
58 | |||
59 | static 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 | |||
86 | static 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 | 41 | extern 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 | |||
130 | static 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 | |||
144 | extern void printascii(const char *); | ||
145 | |||
146 | void 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 | |||
158 | static 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 | |||
177 | static struct sleep_save uart_save[] = {}; | ||
178 | #endif | 45 | #endif |
179 | 46 | ||
180 | #if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0 | 47 | static 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 | |||
194 | static u32 crc_size; /* size needed for the crc block */ | ||
195 | static u32 *crcs; /* allocated over suspend/resume */ | ||
196 | |||
197 | typedef 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 | |||
204 | static 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 | |||
221 | static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg) | ||
222 | { | ||
223 | s3c2410_pm_run_res(&iomem_resource, fn, arg); | ||
224 | } | ||
225 | |||
226 | static 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 | |||
247 | static 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 | ||
260 | static 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 | |||
284 | static 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 | |||
296 | static 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 | |||
307 | static 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 | |||
358 | static 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 | 90 | static 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 | |||
376 | void 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 | ||
392 | void 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 | ||
410 | static 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 | 106 | static int s3c2410_pm_add(struct sys_device *dev) |
418 | * | ||
419 | * print any IRQs asserted at resume time (ie, we woke from) | ||
420 | */ | ||
421 | |||
422 | static 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 | * | 115 | static 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 | |||
442 | static 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 | ||
471 | static void s3c2410_pm_configure_extint(void) | 122 | static 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 | ||
489 | void (*pm_cpu_prep)(void); | 127 | arch_initcall(s3c2410_pm_drvinit); |
490 | void (*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 | |||
499 | static 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; | 131 | static struct sysdev_driver s3c2440_pm_driver = { |
618 | } | 132 | .add = s3c2410_pm_add, |
133 | .resume = s3c2410_pm_resume, | ||
134 | }; | ||
619 | 135 | ||
620 | /* | 136 | static int __init s3c2440_pm_drvinit(void) |
621 | * Called after processes are frozen, but before we shut down devices. | ||
622 | */ | ||
623 | static 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 | /* | 141 | arch_initcall(s3c2440_pm_drvinit); |
629 | * Called after devices are re-setup, but before processes are thawed. | 142 | #endif |
630 | */ | ||
631 | static 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. | 145 | static struct sysdev_driver s3c2442_pm_driver = { |
638 | */ | 146 | .add = s3c2410_pm_add, |
639 | static 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 | 150 | static 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 | |||
653 | int __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 | |||
155 | arch_initcall(s3c2442_pm_drvinit); | ||
156 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/pm.h b/arch/arm/mach-s3c2410/pm.h deleted file mode 100644 index ffe197a119fb..000000000000 --- a/arch/arm/mach-s3c2410/pm.h +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/pm.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Written by Ben Dooks, <ben@simtec.co.uk> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | /* s3c2410_pm_init | ||
12 | * | ||
13 | * called from board at initialisation time to setup the power | ||
14 | * management | ||
15 | */ | ||
16 | |||
17 | #ifdef CONFIG_PM | ||
18 | |||
19 | extern __init int s3c2410_pm_init(void); | ||
20 | |||
21 | #else | ||
22 | |||
23 | static inline int s3c2410_pm_init(void) | ||
24 | { | ||
25 | return 0; | ||
26 | } | ||
27 | #endif | ||
28 | |||
29 | /* configuration for the IRQ mask over sleep */ | ||
30 | extern unsigned long s3c_irqwake_intmask; | ||
31 | extern unsigned long s3c_irqwake_eintmask; | ||
32 | |||
33 | /* IRQ masks for IRQs allowed to go to sleep (see irq.c) */ | ||
34 | extern unsigned long s3c_irqwake_intallow; | ||
35 | extern unsigned long s3c_irqwake_eintallow; | ||
36 | |||
37 | /* per-cpu sleep functions */ | ||
38 | |||
39 | extern void (*pm_cpu_prep)(void); | ||
40 | extern void (*pm_cpu_sleep)(void); | ||
41 | |||
42 | /* Flags for PM Control */ | ||
43 | |||
44 | extern unsigned long s3c_pm_flags; | ||
45 | |||
46 | /* from sleep.S */ | ||
47 | |||
48 | extern int s3c2410_cpu_save(unsigned long *saveblk); | ||
49 | extern void s3c2410_cpu_suspend(void); | ||
50 | extern void s3c2410_cpu_resume(void); | ||
51 | |||
52 | extern unsigned long s3c2410_sleep_save_phys; | ||
53 | |||
54 | /* sleep save info */ | ||
55 | |||
56 | struct sleep_save { | ||
57 | void __iomem *reg; | ||
58 | unsigned long val; | ||
59 | }; | ||
60 | |||
61 | #define SAVE_ITEM(x) \ | ||
62 | { .reg = (x) } | ||
63 | |||
64 | extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count); | ||
65 | extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count); | ||
66 | |||
67 | #ifdef CONFIG_PM | ||
68 | extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state); | ||
69 | extern int s3c24xx_irq_resume(struct sys_device *dev); | ||
70 | #else | ||
71 | #define s3c24xx_irq_suspend NULL | ||
72 | #define s3c24xx_irq_resume NULL | ||
73 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/s3c2400.h b/arch/arm/mach-s3c2410/s3c2400.h deleted file mode 100644 index 8b2394e1ed40..000000000000 --- a/arch/arm/mach-s3c2410/s3c2400.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/s3c2400.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for S3C2400 cpu support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Modifications: | ||
13 | * 09-Fev-2006 LCVR First version, based on s3c2410.h | ||
14 | */ | ||
15 | |||
16 | #ifdef CONFIG_CPU_S3C2400 | ||
17 | |||
18 | extern int s3c2400_init(void); | ||
19 | |||
20 | extern void s3c2400_map_io(struct map_desc *mach_desc, int size); | ||
21 | |||
22 | extern void s3c2400_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
23 | |||
24 | extern void s3c2400_init_clocks(int xtal); | ||
25 | |||
26 | #else | ||
27 | #define s3c2400_init_clocks NULL | ||
28 | #define s3c2400_init_uarts NULL | ||
29 | #define s3c2400_map_io NULL | ||
30 | #define s3c2400_init NULL | ||
31 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c deleted file mode 100644 index 992cc6af230e..000000000000 --- a/arch/arm/mach-s3c2410/s3c2410-clock.c +++ /dev/null | |||
@@ -1,276 +0,0 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/s3c2410-clock.c | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * S3C2410,S3C2440,S3C2442 Clock control support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/sysdev.h> | ||
30 | #include <linux/clk.h> | ||
31 | #include <linux/mutex.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/serial_core.h> | ||
34 | |||
35 | #include <asm/mach/map.h> | ||
36 | |||
37 | #include <asm/hardware.h> | ||
38 | #include <asm/io.h> | ||
39 | |||
40 | #include <asm/arch/regs-serial.h> | ||
41 | #include <asm/arch/regs-clock.h> | ||
42 | #include <asm/arch/regs-gpio.h> | ||
43 | |||
44 | #include "s3c2410.h" | ||
45 | #include "clock.h" | ||
46 | #include "cpu.h" | ||
47 | |||
48 | int 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 | |||
68 | static 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 | |||
90 | static 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 | |||
130 | static 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 | |||
211 | int __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 | |||
35 | static 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 | |||
117 | static 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 | |||
123 | static 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 | |||
130 | static 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) | ||
136 | static struct sysdev_driver s3c2410_dma_driver = { | ||
137 | .add = s3c2410_dma_add, | ||
138 | }; | ||
139 | |||
140 | static int __init s3c2410_dma_init(void) | ||
141 | { | ||
142 | return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_dma_driver); | ||
143 | } | ||
144 | |||
145 | arch_initcall(s3c2410_dma_init); | ||
146 | #endif | ||
147 | |||
148 | #if defined(CONFIG_CPU_S3C2442) | ||
149 | /* S3C2442 DMA contains the same selection table as the S3C2410 */ | ||
150 | static struct sysdev_driver s3c2442_dma_driver = { | ||
151 | .add = s3c2410_dma_add, | ||
152 | }; | ||
153 | |||
154 | static int __init s3c2442_dma_init(void) | ||
155 | { | ||
156 | return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_dma_driver); | ||
157 | } | ||
158 | |||
159 | arch_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 | |||
35 | int 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 | |||
71 | EXPORT_SYMBOL(s3c2410_gpio_irqfilter); | ||
diff --git a/arch/arm/mach-s3c2410/s3c2410-irq.c b/arch/arm/mach-s3c2410/s3c2410-irq.c deleted file mode 100644 index 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 | |||
32 | static int s3c2410_irq_add(struct sys_device *sysdev) | ||
33 | { | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static struct sysdev_driver s3c2410_irq_driver = { | ||
38 | .add = s3c2410_irq_add, | ||
39 | .suspend = s3c24xx_irq_suspend, | ||
40 | .resume = s3c24xx_irq_resume, | ||
41 | }; | ||
42 | |||
43 | static int s3c2410_irq_init(void) | ||
44 | { | ||
45 | return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver); | ||
46 | } | ||
47 | |||
48 | arch_initcall(s3c2410_irq_init); | ||
diff --git a/arch/arm/mach-s3c2410/s3c2410-pm.c b/arch/arm/mach-s3c2410/s3c2410-pm.c deleted file mode 100644 index 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 | ||
41 | extern 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 | |||
47 | static 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 | |||
90 | static 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 | |||
106 | static 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) | ||
115 | static struct sysdev_driver s3c2410_pm_driver = { | ||
116 | .add = s3c2410_pm_add, | ||
117 | .resume = s3c2410_pm_resume, | ||
118 | }; | ||
119 | |||
120 | /* register ourselves */ | ||
121 | |||
122 | static int __init s3c2410_pm_drvinit(void) | ||
123 | { | ||
124 | return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_pm_driver); | ||
125 | } | ||
126 | |||
127 | arch_initcall(s3c2410_pm_drvinit); | ||
128 | #endif | ||
129 | |||
130 | #if defined(CONFIG_CPU_S3C2440) | ||
131 | static struct sysdev_driver s3c2440_pm_driver = { | ||
132 | .add = s3c2410_pm_add, | ||
133 | .resume = s3c2410_pm_resume, | ||
134 | }; | ||
135 | |||
136 | static int __init s3c2440_pm_drvinit(void) | ||
137 | { | ||
138 | return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_pm_driver); | ||
139 | } | ||
140 | |||
141 | arch_initcall(s3c2440_pm_drvinit); | ||
142 | #endif | ||
143 | |||
144 | #if defined(CONFIG_CPU_S3C2442) | ||
145 | static struct sysdev_driver s3c2442_pm_driver = { | ||
146 | .add = s3c2410_pm_add, | ||
147 | .resume = s3c2410_pm_resume, | ||
148 | }; | ||
149 | |||
150 | static int __init s3c2442_pm_drvinit(void) | ||
151 | { | ||
152 | return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_pm_driver); | ||
153 | } | ||
154 | |||
155 | arch_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 | |||
42 | ENTRY(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 | ||
63 | s3c2410_do_sleep: | ||
64 | streq r7, [ r4 ] @ SDRAM sleep command | ||
65 | streq r8, [ r5 ] @ SDRAM power-down config | ||
66 | streq r9, [ r6 ] @ CPU sleep | ||
67 | 1: beq 1b | ||
68 | mov pc, r14 | ||
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index 4cdc0d70c19f..1a86a9803753 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c | |||
@@ -31,10 +31,10 @@ | |||
31 | #include <asm/arch/regs-clock.h> | 31 | #include <asm/arch/regs-clock.h> |
32 | #include <asm/arch/regs-serial.h> | 32 | #include <asm/arch/regs-serial.h> |
33 | 33 | ||
34 | #include "s3c2410.h" | 34 | #include <asm/plat-s3c24xx/s3c2410.h> |
35 | #include "cpu.h" | 35 | #include <asm/plat-s3c24xx/cpu.h> |
36 | #include "devs.h" | 36 | #include <asm/plat-s3c24xx/devs.h> |
37 | #include "clock.h" | 37 | #include <asm/plat-s3c24xx/clock.h> |
38 | 38 | ||
39 | /* Initial IO mappings */ | 39 | /* Initial IO mappings */ |
40 | 40 | ||
@@ -110,7 +110,7 @@ static struct sys_device s3c2410_sysdev = { | |||
110 | 110 | ||
111 | /* need to register class before we actually register the device, and | 111 | /* need to register class before we actually register the device, and |
112 | * we also need to ensure that it has been initialised before any of the | 112 | * we also need to ensure that it has been initialised before any of the |
113 | * drivers even try to use it (even if not on an s3c2440 based system) | 113 | * drivers even try to use it (even if not on an s3c2410 based system) |
114 | * as a driver which may support both 2410 and 2440 may try and use it. | 114 | * as a driver which may support both 2410 and 2440 may try and use it. |
115 | */ | 115 | */ |
116 | 116 | ||
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h deleted file mode 100644 index fbed084f26d0..000000000000 --- a/arch/arm/mach-s3c2410/s3c2410.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/s3c2410.h | ||
2 | * | ||
3 | * Copyright (c) 2004 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for s3c2410 machine directory | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifdef CONFIG_CPU_S3C2410 | ||
15 | |||
16 | extern int s3c2410_init(void); | ||
17 | |||
18 | extern void s3c2410_map_io(struct map_desc *mach_desc, int size); | ||
19 | |||
20 | extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
21 | |||
22 | extern void s3c2410_init_clocks(int xtal); | ||
23 | |||
24 | extern int s3c2410_baseclk_add(void); | ||
25 | |||
26 | #else | ||
27 | #define s3c2410_init_clocks NULL | ||
28 | #define s3c2410_init_uarts NULL | ||
29 | #define s3c2410_map_io NULL | ||
30 | #define s3c2410_init NULL | ||
31 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h deleted file mode 100644 index c6e56032a6e7..000000000000 --- a/arch/arm/mach-s3c2410/s3c2412.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/s3c2412.h | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for s3c2412 cpu support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifdef CONFIG_CPU_S3C2412 | ||
14 | |||
15 | extern int s3c2412_init(void); | ||
16 | |||
17 | extern void s3c2412_map_io(struct map_desc *mach_desc, int size); | ||
18 | |||
19 | extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no); | ||
20 | |||
21 | extern void s3c2412_init_clocks(int xtal); | ||
22 | |||
23 | extern int s3c2412_baseclk_add(void); | ||
24 | #else | ||
25 | #define s3c2412_init_clocks NULL | ||
26 | #define s3c2412_init_uarts NULL | ||
27 | #define s3c2412_map_io NULL | ||
28 | #define s3c2412_init NULL | ||
29 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/s3c2440.h b/arch/arm/mach-s3c2410/s3c2440.h deleted file mode 100644 index dcd316076c59..000000000000 --- a/arch/arm/mach-s3c2410/s3c2440.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/s3c2440.h | ||
2 | * | ||
3 | * Copyright (c) 2004-2005 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for s3c2440 cpu support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifdef CONFIG_CPU_S3C2440 | ||
14 | extern int s3c2440_init(void); | ||
15 | #else | ||
16 | #define s3c2440_init NULL | ||
17 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h deleted file mode 100644 index 0ae37d24866c..000000000000 --- a/arch/arm/mach-s3c2410/s3c2442.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | /* arch/arm/mach-s3c2410/s3c2442.h | ||
2 | * | ||
3 | * Copyright (c) 2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * Header file for s3c2442 cpu support | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifdef CONFIG_CPU_S3C2442 | ||
14 | extern int s3c2442_init(void); | ||
15 | #else | ||
16 | #define s3c2442_init NULL | ||
17 | #endif | ||
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S index 2018c2e1dcc5..637aaba65390 100644 --- a/arch/arm/mach-s3c2410/sleep.S +++ b/arch/arm/mach-s3c2410/sleep.S | |||
@@ -1,4 +1,4 @@ | |||
1 | /* linux/arch/arm/mach-s3c2410/sleep.S | 1 | /* linux/arch/arm/mach-s3c2410/s3c2410-sleep.S |
2 | * | 2 | * |
3 | * Copyright (c) 2004 Simtec Electronics | 3 | * Copyright (c) 2004 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 4 | * Ben Dooks <ben@simtec.co.uk> |
@@ -34,126 +34,35 @@ | |||
34 | #include <asm/arch/regs-mem.h> | 34 | #include <asm/arch/regs-mem.h> |
35 | #include <asm/arch/regs-serial.h> | 35 | #include <asm/arch/regs-serial.h> |
36 | 36 | ||
37 | /* CONFIG_DEBUG_RESUME is dangerous if your bootloader does not | 37 | /* s3c2410_cpu_suspend |
38 | * reset the UART configuration, only enable if you really need this! | ||
39 | */ | ||
40 | //#define CONFIG_DEBUG_RESUME | ||
41 | |||
42 | .text | ||
43 | |||
44 | /* s3c2410_cpu_save | ||
45 | * | ||
46 | * save enough of the CPU state to allow us to re-start | ||
47 | * pm.c code. as we store items like the sp/lr, we will | ||
48 | * end up returning from this function when the cpu resumes | ||
49 | * so the return value is set to mark this. | ||
50 | * | ||
51 | * This arangement means we avoid having to flush the cache | ||
52 | * from this code. | ||
53 | * | ||
54 | * entry: | ||
55 | * r0 = pointer to save block | ||
56 | * | ||
57 | * exit: | ||
58 | * r0 = 0 => we stored everything | ||
59 | * 1 => resumed from sleep | ||
60 | */ | ||
61 | |||
62 | ENTRY(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 | ||
81 | resume_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 | ||
97 | s3c2410_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 | ||
109 | ENTRY(s3c2410_cpu_resume) | 42 | ENTRY(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 ] | 63 | s3c2410_do_sleep: |
131 | 1001: | 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 | 67 | 1: 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 | |||
7 | config 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 | |||
15 | config 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 | |||
21 | config S3C2412_DMA | ||
22 | bool | ||
23 | depends on CPU_S3C2412 | ||
24 | help | ||
25 | Internal config node for S3C2412 DMA support | ||
26 | |||
27 | config S3C2412_PM | ||
28 | bool | ||
29 | help | ||
30 | Internal config node to apply S3C2412 power management | ||
31 | |||
32 | |||
33 | menu "S3C2412 Machines" | ||
34 | |||
35 | config 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 | |||
43 | config 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 | |||
50 | config MACH_VSTMS | ||
51 | bool "VMSTMS" | ||
52 | select CPU_S3C2412 | ||
53 | help | ||
54 | Say Y here if you are using an VSTMS board | ||
55 | |||
56 | |||
57 | endmenu | ||
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 | |||
7 | obj-y := | ||
8 | obj-m := | ||
9 | obj-n := | ||
10 | obj- := | ||
11 | |||
12 | obj-$(CONFIG_CPU_S3C2412) += s3c2412.o | ||
13 | obj-$(CONFIG_CPU_S3C2412) += irq.o | ||
14 | obj-$(CONFIG_CPU_S3C2412) += clock.o | ||
15 | obj-$(CONFIG_S3C2412_DMA) += dma.o | ||
16 | obj-$(CONFIG_S3C2412_PM) += pm.o | ||
17 | |||
18 | # Machine support | ||
19 | |||
20 | obj-$(CONFIG_MACH_SMDK2413) += mach-smdk2413.o | ||
21 | obj-$(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 | ||
147 | static int s3c2412_dma_add(struct sys_device *sysdev) | 147 | static 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 | ||
50 | static struct map_desc smdk2413_iodesc[] __initdata = { | 51 | static 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 | ||
79 | static 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 | |||
99 | static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = { | ||
100 | .udc_command = smdk2413_udc_pullup, | ||
101 | }; | ||
102 | |||
103 | |||
78 | static struct platform_device *smdk2413_devices[] __initdata = { | 104 | static 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 | ||
86 | static struct s3c24xx_board smdk2413_board __initdata = { | 113 | static struct s3c24xx_board smdk2413_board __initdata = { |
@@ -109,7 +136,19 @@ static void __init smdk2413_map_io(void) | |||
109 | } | 136 | } |
110 | 137 | ||
111 | static void __init smdk2413_machine_init(void) | 138 | static 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, |
127 | MACHINE_END | 166 | MACHINE_END |
128 | 167 | ||
168 | MACHINE_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, | ||
179 | MACHINE_END | ||
180 | |||
129 | MACHINE_START(SMDK2413, "SMDK2413") | 181 | MACHINE_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 | ||
53 | static struct map_desc vstms_iodesc[] __initdata = { | 52 | static 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 | ||
36 | static void s3c2412_cpu_suspend(void) | 36 | static 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 |
48 | void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; | 48 | void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; |
diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig new file mode 100644 index 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 | |||
7 | config 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 | |||
18 | config S3C2440_DMA | ||
19 | bool | ||
20 | depends on ARCH_S3C2410 && CPU_S3C24405B | ||
21 | help | ||
22 | Support for S3C2440 specific DMA code5A | ||
23 | |||
24 | |||
25 | menu "S3C2440 Machines" | ||
26 | |||
27 | config 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 | |||
35 | config 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 | |||
43 | config 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 | |||
50 | config 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 | |||
57 | config 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 | |||
63 | config 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 | |||
70 | endmenu | ||
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 | |||
7 | obj-y := | ||
8 | obj-m := | ||
9 | obj-n := | ||
10 | obj- := | ||
11 | |||
12 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o dsc.o | ||
13 | obj-$(CONFIG_CPU_S3C2440) += irq.o | ||
14 | obj-$(CONFIG_CPU_S3C2440) += clock.o | ||
15 | obj-$(CONFIG_S3C2440_DMA) += dma.o | ||
16 | |||
17 | # Machine support | ||
18 | |||
19 | obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o | ||
20 | obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o | ||
21 | obj-$(CONFIG_MACH_RX3715) += mach-rx3715.o | ||
22 | obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o | ||
23 | obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o | ||
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2440/clock.c 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 | ||
150 | static 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 | |||
150 | static int s3c2440_dma_add(struct sys_device *sysdev) | 193 | static 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 | ||
33 | int s3c2440_set_dsc(unsigned int pin, unsigned int value) | 33 | int 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 | ||
47 | static struct map_desc nexcoder_iodesc[] __initdata = { | 47 | static 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 | ||
54 | static struct map_desc rx3715_iodesc[] __initdata = { | 53 | static 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 | ||
51 | static struct map_desc smdk2440_iodesc[] __initdata = { | 49 | static 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 | ||
36 | static struct sys_device s3c2440_sysdev = { | 36 | static 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 | |||
7 | config 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 | |||
18 | menu "S3C2442 Machines" | ||
19 | |||
20 | config SMDK2440_CPU2442 | ||
21 | bool "SMDM2440 with S3C2442 CPU module" | ||
22 | depends on ARCH_S3C2440 | ||
23 | select CPU_S3C2442 | ||
24 | |||
25 | |||
26 | endmenu | ||
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 | |||
7 | obj-y := | ||
8 | obj-m := | ||
9 | obj-n := | ||
10 | obj- := | ||
11 | |||
12 | obj-$(CONFIG_CPU_S3C2442) += s3c2442.o | ||
13 | obj-$(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 | ||
25 | static struct sys_device s3c2442_sysdev = { | 25 | static 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 | |||
7 | config 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 | |||
14 | config S3C2443_DMA | ||
15 | bool | ||
16 | depends on CPU_S3C2443 | ||
17 | help | ||
18 | Internal config node for S3C2443 DMA support | ||
19 | |||
20 | menu "S3C2443 Machines" | ||
21 | |||
22 | config 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 | |||
29 | endmenu | ||
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 | |||
7 | obj-y := | ||
8 | obj-m := | ||
9 | obj-n := | ||
10 | obj- := | ||
11 | |||
12 | obj-$(CONFIG_CPU_S3C2443) += s3c2443.o | ||
13 | obj-$(CONFIG_CPU_S3C2443) += irq.o | ||
14 | obj-$(CONFIG_CPU_S3C2443) += clock.o | ||
15 | |||
16 | obj-$(CONFIG_S3C2443_DMA) += dma.o | ||
17 | |||
18 | # Machine support | ||
19 | |||
20 | obj-$(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 | |||
55 | static 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 | |||
72 | static 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 | |||
89 | static 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 | |||
106 | static 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 | |||
128 | static unsigned long s3c2443_roundrate_clksrc4(struct clk *clk, | ||
129 | unsigned long rate) | ||
130 | { | ||
131 | return s3c2443_roundrate_clksrc(clk, rate, 4); | ||
132 | } | ||
133 | |||
134 | static unsigned long s3c2443_roundrate_clksrc16(struct clk *clk, | ||
135 | unsigned long rate) | ||
136 | { | ||
137 | return s3c2443_roundrate_clksrc(clk, rate, 16); | ||
138 | } | ||
139 | |||
140 | static 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 */ | ||
149 | static struct clk clk_ext = { | ||
150 | .name = "ext", | ||
151 | .id = -1, | ||
152 | }; | ||
153 | |||
154 | static struct clk clk_mpllref = { | ||
155 | .name = "mpllref", | ||
156 | .parent = &clk_xtal, | ||
157 | .id = -1, | ||
158 | }; | ||
159 | |||
160 | #if 0 | ||
161 | static struct clk clk_mpll = { | ||
162 | .name = "mpll", | ||
163 | .parent = &clk_mpllref, | ||
164 | .id = -1, | ||
165 | }; | ||
166 | #endif | ||
167 | |||
168 | static struct clk clk_epllref; | ||
169 | |||
170 | static struct clk clk_epll = { | ||
171 | .name = "epll", | ||
172 | .parent = &clk_epllref, | ||
173 | .id = -1, | ||
174 | }; | ||
175 | |||
176 | static struct clk clk_i2s_ext = { | ||
177 | .name = "i2s-ext", | ||
178 | .id = -1, | ||
179 | }; | ||
180 | |||
181 | static 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 | |||
200 | static struct clk clk_epllref = { | ||
201 | .name = "epllref", | ||
202 | .id = -1, | ||
203 | .set_parent = s3c2443_setparent_epllref, | ||
204 | }; | ||
205 | |||
206 | static 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 | |||
217 | static struct clk clk_mdivclk = { | ||
218 | .name = "mdivclk", | ||
219 | .parent = &clk_mpllref, | ||
220 | .id = -1, | ||
221 | .get_rate = s3c2443_getrate_mdivclk, | ||
222 | }; | ||
223 | |||
224 | |||
225 | static 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 | |||
245 | static 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 | |||
258 | static 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 | |||
275 | static 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 | |||
287 | static 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 | |||
299 | static 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 | |||
314 | static 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 | |||
328 | static 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 | |||
340 | static 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 | |||
355 | static 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 | |||
371 | static 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 | |||
382 | static 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 | |||
397 | struct 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 | |||
415 | static 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 | |||
426 | static 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 | |||
441 | static 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 | |||
450 | static 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 | |||
472 | static int s3c2443_enable_hsmmc(struct clk *clk, int enable) | ||
473 | { | ||
474 | return s3c2443_setparent_hsmmc(clk, clk->parent); | ||
475 | } | ||
476 | |||
477 | static 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 | |||
490 | static 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 | |||
501 | static 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 | |||
516 | static 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 | |||
530 | static 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 | |||
549 | static 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 | |||
563 | static 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 | |||
574 | static 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 | |||
589 | static 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 | |||
605 | static 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 | |||
616 | static 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 | |||
631 | static 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 | |||
644 | static 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 | |||
688 | static 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 | |||
804 | static 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 | |||
810 | static 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 | |||
871 | static 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 | |||
882 | static 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 | |||
889 | static 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 | |||
899 | static 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 | |||
918 | void __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 | |||
45 | static 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 | |||
151 | static 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 | |||
158 | static 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 | |||
165 | static 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 | |||
171 | static struct sysdev_driver s3c2443_dma_driver = { | ||
172 | .add = s3c2443_dma_add, | ||
173 | }; | ||
174 | |||
175 | static int __init s3c2443_dma_init(void) | ||
176 | { | ||
177 | return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_dma_driver); | ||
178 | } | ||
179 | |||
180 | arch_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 | |||
44 | static 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 | |||
74 | static 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 | |||
82 | static void s3c2443_irq_wdtac97_mask(unsigned int irqno) | ||
83 | { | ||
84 | s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
85 | } | ||
86 | |||
87 | static void s3c2443_irq_wdtac97_unmask(unsigned int irqno) | ||
88 | { | ||
89 | s3c_irqsub_unmask(irqno, INTMSK_WDTAC97); | ||
90 | } | ||
91 | |||
92 | static void s3c2443_irq_wdtac97_ack(unsigned int irqno) | ||
93 | { | ||
94 | s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
95 | } | ||
96 | |||
97 | static 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 | |||
106 | static 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 | |||
114 | static void s3c2443_irq_lcd_mask(unsigned int irqno) | ||
115 | { | ||
116 | s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD); | ||
117 | } | ||
118 | |||
119 | static void s3c2443_irq_lcd_unmask(unsigned int irqno) | ||
120 | { | ||
121 | s3c_irqsub_unmask(irqno, INTMSK_LCD); | ||
122 | } | ||
123 | |||
124 | static void s3c2443_irq_lcd_ack(unsigned int irqno) | ||
125 | { | ||
126 | s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD); | ||
127 | } | ||
128 | |||
129 | static 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 | |||
138 | static 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 | |||
147 | static void s3c2443_irq_dma_mask(unsigned int irqno) | ||
148 | { | ||
149 | s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA); | ||
150 | } | ||
151 | |||
152 | static void s3c2443_irq_dma_unmask(unsigned int irqno) | ||
153 | { | ||
154 | s3c_irqsub_unmask(irqno, INTMSK_DMA); | ||
155 | } | ||
156 | |||
157 | static void s3c2443_irq_dma_ack(unsigned int irqno) | ||
158 | { | ||
159 | s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA); | ||
160 | } | ||
161 | |||
162 | static 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 | |||
171 | static 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 | |||
180 | static void s3c2443_irq_uart3_mask(unsigned int irqno) | ||
181 | { | ||
182 | s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3); | ||
183 | } | ||
184 | |||
185 | static void s3c2443_irq_uart3_unmask(unsigned int irqno) | ||
186 | { | ||
187 | s3c_irqsub_unmask(irqno, INTMSK_UART3); | ||
188 | } | ||
189 | |||
190 | static void s3c2443_irq_uart3_ack(unsigned int irqno) | ||
191 | { | ||
192 | s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3); | ||
193 | } | ||
194 | |||
195 | static 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 | |||
204 | static 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 | |||
212 | static void s3c2443_irq_cam_mask(unsigned int irqno) | ||
213 | { | ||
214 | s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM); | ||
215 | } | ||
216 | |||
217 | static void s3c2443_irq_cam_unmask(unsigned int irqno) | ||
218 | { | ||
219 | s3c_irqsub_unmask(irqno, INTMSK_CAM); | ||
220 | } | ||
221 | |||
222 | static void s3c2443_irq_cam_ack(unsigned int irqno) | ||
223 | { | ||
224 | s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM); | ||
225 | } | ||
226 | |||
227 | static 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 | |||
235 | static 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 | |||
256 | static 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 | |||
280 | static struct sysdev_driver s3c2443_irq_driver = { | ||
281 | .add = s3c2443_irq_add, | ||
282 | }; | ||
283 | |||
284 | static int s3c2443_irq_init(void) | ||
285 | { | ||
286 | return sysdev_driver_register(&s3c2443_sysclass, &s3c2443_irq_driver); | ||
287 | } | ||
288 | |||
289 | arch_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 | |||
49 | static 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 | |||
79 | static 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 | |||
104 | static struct platform_device *smdk2443_devices[] __initdata = { | ||
105 | &s3c_device_wdt, | ||
106 | &s3c_device_i2c, | ||
107 | }; | ||
108 | |||
109 | static struct s3c24xx_board smdk2443_board __initdata = { | ||
110 | .devices = smdk2443_devices, | ||
111 | .devices_count = ARRAY_SIZE(smdk2443_devices) | ||
112 | }; | ||
113 | |||
114 | static 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 | |||
122 | static void __init smdk2443_machine_init(void) | ||
123 | { | ||
124 | smdk_machine_init(); | ||
125 | } | ||
126 | |||
127 | MACHINE_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, | ||
137 | MACHINE_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 | |||
39 | static struct map_desc s3c2443_iodesc[] __initdata = { | ||
40 | IODESC_ENT(WATCHDOG), | ||
41 | IODESC_ENT(CLKPWR), | ||
42 | IODESC_ENT(TIMER), | ||
43 | }; | ||
44 | |||
45 | struct sysdev_class s3c2443_sysclass = { | ||
46 | set_kset_name("s3c2443-core"), | ||
47 | }; | ||
48 | |||
49 | static struct sys_device s3c2443_sysdev = { | ||
50 | .cls = &s3c2443_sysclass, | ||
51 | }; | ||
52 | |||
53 | static void s3c2443_hard_reset(void) | ||
54 | { | ||
55 | __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST); | ||
56 | } | ||
57 | |||
58 | int __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 | |||
69 | void __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 | |||
80 | void __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 | |||
92 | static int __init s3c2443_core_init(void) | ||
93 | { | ||
94 | return sysdev_class_register(&s3c2443_sysclass); | ||
95 | } | ||
96 | |||
97 | core_initcall(s3c2443_core_init); | ||
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index aade2f72c920..da8f043dc2cc 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
@@ -171,8 +171,8 @@ config CPU_ARM925T | |||
171 | # ARM926T | 171 | # ARM926T |
172 | config CPU_ARM926T | 172 | config CPU_ARM926T |
173 | bool "Support ARM926T processor" | 173 | bool "Support ARM926T processor" |
174 | depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 | 174 | depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 |
175 | default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 | 175 | default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 |
176 | select CPU_32v5 | 176 | select CPU_32v5 |
177 | select CPU_ABRT_EV5TJ | 177 | select CPU_ABRT_EV5TJ |
178 | select CPU_CACHE_VIVT | 178 | select CPU_CACHE_VIVT |
@@ -609,3 +609,10 @@ config NEEDS_SYSCALL_FOR_CMPXCHG | |||
609 | Forget about fast user space cmpxchg support. | 609 | Forget about fast user space cmpxchg support. |
610 | It is just not possible. | 610 | It is just not possible. |
611 | 611 | ||
612 | config OUTER_CACHE | ||
613 | bool | ||
614 | default n | ||
615 | |||
616 | config 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 | |||
66 | obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o | 66 | obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o |
67 | obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o | 67 | obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o |
68 | obj-$(CONFIG_CPU_V6) += proc-v6.o | 68 | obj-$(CONFIG_CPU_V6) += proc-v6.o |
69 | |||
70 | obj-$(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 | |||
27 | static void __iomem *l2x0_base; | ||
28 | |||
29 | static 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 | |||
38 | static inline void cache_sync(void) | ||
39 | { | ||
40 | sync_writel(0, L2X0_CACHE_SYNC, 1); | ||
41 | } | ||
42 | |||
43 | static inline void l2x0_inv_all(void) | ||
44 | { | ||
45 | /* invalidate all ways */ | ||
46 | sync_writel(0xff, L2X0_INV_WAY, 0xff); | ||
47 | cache_sync(); | ||
48 | } | ||
49 | |||
50 | static 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 | |||
60 | static 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 | |||
70 | static 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 | |||
80 | void __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 | */ |
483 | void consistent_sync(void *vaddr, size_t size, int direction) | 484 | void 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 | */ |
24 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) | 25 | void __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 | ||
122 | void __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 | ||
50 | static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK; | 50 | static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK; |
51 | static unsigned int ecc_mask __initdata = 0; | 51 | static unsigned int ecc_mask __initdata = 0; |
52 | pgprot_t pgprot_user; | ||
52 | pgprot_t pgprot_kernel; | 53 | pgprot_t pgprot_kernel; |
53 | 54 | ||
55 | EXPORT_SYMBOL(pgprot_user); | ||
54 | EXPORT_SYMBOL(pgprot_kernel); | 56 | EXPORT_SYMBOL(pgprot_kernel); |
55 | 57 | ||
56 | struct cachepolicy { | 58 | struct 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 | |||
33 | ENTRY(cpu_v6_proc_init) | 42 | ENTRY(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 |
77 | 1: mcr p15, 0, \rd, c7, c14, 2 @ clean/inv set/way | 77 | 1: 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 | ||
147 | ENTRY(cpu_xsc3_do_idle) | 145 | ENTRY(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 | ||
196 | 1: tst r2, #VM_EXEC | 194 | 1: 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 */ |
223 | ENTRY(xsc3_coherent_user_range) | 221 | ENTRY(xsc3_coherent_user_range) |
224 | bic r0, r0, #CACHELINESIZE - 1 | 222 | bic r0, r0, #CACHELINESIZE - 1 |
225 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | 223 | 1: 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 | */ |
243 | ENTRY(xsc3_flush_kern_dcache_page) | 241 | ENTRY(xsc3_flush_kern_dcache_page) |
244 | add r1, r0, #PAGE_SZ | 242 | add r1, r0, #PAGE_SZ |
245 | 1: mcr p15, 0, r0, c7, c14, 1 @ Clean/Invalidate D Cache line | 243 | 1: 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) | |||
266 | ENTRY(xsc3_dma_inv_range) | 264 | ENTRY(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 |
274 | 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D entry | 272 | 1: 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 | */ |
290 | ENTRY(xsc3_dma_clean_range) | 288 | ENTRY(xsc3_dma_clean_range) |
291 | bic r0, r0, #CACHELINESIZE - 1 | 289 | bic r0, r0, #CACHELINESIZE - 1 |
292 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D entry | 290 | 1: 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 | */ |
308 | ENTRY(xsc3_dma_flush_range) | 306 | ENTRY(xsc3_dma_flush_range) |
309 | bic r0, r0, #CACHELINESIZE - 1 | 307 | bic r0, r0, #CACHELINESIZE - 1 |
310 | 1: mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate L1 D cache line | 308 | 1: 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 | ||
319 | ENTRY(xsc3_cache_fns) | 317 | ENTRY(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 | ||
330 | ENTRY(cpu_xsc3_dcache_clean_area) | 328 | ENTRY(cpu_xsc3_dcache_clean_area) |
331 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | 329 | 1: 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 |
347 | ENTRY(cpu_xsc3_switch_mm) | 345 | ENTRY(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) | |||
366 | ENTRY(cpu_xsc3_set_pte_ext) | 364 | ENTRY(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 |
441 | xsc3_crval: | 440 | xsc3_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 |
476 | cpu_xsc3_name: | 475 | cpu_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 | |||
7 | config 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 | |||
14 | if PLAT_S3C24XX | ||
15 | |||
16 | config 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 | |||
22 | config 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 | |||
28 | config 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 | |||
36 | config 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 | |||
43 | config 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 | |||
51 | config 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 | |||
60 | config 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 | |||
70 | config 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 | |||
79 | config 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 | |||
87 | config 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 | |||
94 | config MACH_SMDK | ||
95 | bool | ||
96 | help | ||
97 | Common machine code for SMDK2410 and SMDK2440 | ||
98 | |||
99 | endif | ||
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 | |||
7 | obj-y := | ||
8 | obj-m := | ||
9 | obj-n := | ||
10 | obj- := | ||
11 | |||
12 | |||
13 | # Core files | ||
14 | |||
15 | obj-y += cpu.o | ||
16 | obj-y += irq.o | ||
17 | obj-y += devs.o | ||
18 | obj-y += gpio.o | ||
19 | obj-y += time.o | ||
20 | obj-y += clock.o | ||
21 | |||
22 | # Architecture dependant builds | ||
23 | |||
24 | obj-$(CONFIG_CPU_S3C244X) += s3c244x.o | ||
25 | obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o | ||
26 | obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o | ||
27 | obj-$(CONFIG_PM) += pm.o | ||
28 | obj-$(CONFIG_PM) += sleep.o | ||
29 | obj-$(CONFIG_S3C2410_DMA) += dma.o | ||
30 | obj-$(CONFIG_MACH_SMDK) += common-smdk.o | ||
diff --git a/arch/arm/plat-s3c24xx/clock.c b/arch/arm/plat-s3c24xx/clock.c new file mode 100644 index 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 | |||
55 | static LIST_HEAD(clocks); | ||
56 | |||
57 | DEFINE_MUTEX(clocks_mutex); | ||
58 | |||
59 | /* enable and disable calls for use with the clk struct */ | ||
60 | |||
61 | static int clk_null_enable(struct clk *clk, int enable) | ||
62 | { | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* Clock API calls */ | ||
67 | |||
68 | struct 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 | |||
107 | void clk_put(struct clk *clk) | ||
108 | { | ||
109 | module_put(clk->owner); | ||
110 | } | ||
111 | |||
112 | int 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 | |||
128 | void 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 | |||
143 | unsigned 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 | |||
160 | long 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 | |||
168 | int 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 | |||
182 | struct clk *clk_get_parent(struct clk *clk) | ||
183 | { | ||
184 | return clk->parent; | ||
185 | } | ||
186 | |||
187 | int 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 | |||
204 | EXPORT_SYMBOL(clk_get); | ||
205 | EXPORT_SYMBOL(clk_put); | ||
206 | EXPORT_SYMBOL(clk_enable); | ||
207 | EXPORT_SYMBOL(clk_disable); | ||
208 | EXPORT_SYMBOL(clk_get_rate); | ||
209 | EXPORT_SYMBOL(clk_round_rate); | ||
210 | EXPORT_SYMBOL(clk_set_rate); | ||
211 | EXPORT_SYMBOL(clk_get_parent); | ||
212 | EXPORT_SYMBOL(clk_set_parent); | ||
213 | |||
214 | /* base clocks */ | ||
215 | |||
216 | struct clk clk_xtal = { | ||
217 | .name = "xtal", | ||
218 | .id = -1, | ||
219 | .rate = 0, | ||
220 | .parent = NULL, | ||
221 | .ctrlbit = 0, | ||
222 | }; | ||
223 | |||
224 | struct clk clk_mpll = { | ||
225 | .name = "mpll", | ||
226 | .id = -1, | ||
227 | }; | ||
228 | |||
229 | struct clk clk_upll = { | ||
230 | .name = "upll", | ||
231 | .id = -1, | ||
232 | .parent = NULL, | ||
233 | .ctrlbit = 0, | ||
234 | }; | ||
235 | |||
236 | struct clk clk_f = { | ||
237 | .name = "fclk", | ||
238 | .id = -1, | ||
239 | .rate = 0, | ||
240 | .parent = &clk_mpll, | ||
241 | .ctrlbit = 0, | ||
242 | }; | ||
243 | |||
244 | struct clk clk_h = { | ||
245 | .name = "hclk", | ||
246 | .id = -1, | ||
247 | .rate = 0, | ||
248 | .parent = NULL, | ||
249 | .ctrlbit = 0, | ||
250 | }; | ||
251 | |||
252 | struct clk clk_p = { | ||
253 | .name = "pclk", | ||
254 | .id = -1, | ||
255 | .rate = 0, | ||
256 | .parent = NULL, | ||
257 | .ctrlbit = 0, | ||
258 | }; | ||
259 | |||
260 | struct 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 | |||
269 | static 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 | |||
283 | static 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 | |||
317 | static 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 | |||
356 | struct 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 | |||
364 | struct 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 | |||
372 | struct clk s3c24xx_clkout0 = { | ||
373 | .name = "clkout0", | ||
374 | .id = -1, | ||
375 | .set_parent = s3c24xx_clkout_setparent, | ||
376 | }; | ||
377 | |||
378 | struct clk s3c24xx_clkout1 = { | ||
379 | .name = "clkout1", | ||
380 | .id = -1, | ||
381 | .set_parent = s3c24xx_clkout_setparent, | ||
382 | }; | ||
383 | |||
384 | struct clk s3c24xx_uclk = { | ||
385 | .name = "uclk", | ||
386 | .id = -1, | ||
387 | }; | ||
388 | |||
389 | /* initialise the clock system */ | ||
390 | |||
391 | int 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 | |||
409 | int __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 | ||
53 | struct cpu_table { | 54 | struct cpu_table { |
54 | unsigned long idcode; | 55 | unsigned long idcode; |
@@ -67,6 +68,7 @@ static const char name_s3c2410[] = "S3C2410"; | |||
67 | static const char name_s3c2412[] = "S3C2412"; | 68 | static const char name_s3c2412[] = "S3C2412"; |
68 | static const char name_s3c2440[] = "S3C2440"; | 69 | static const char name_s3c2440[] = "S3C2440"; |
69 | static const char name_s3c2442[] = "S3C2442"; | 70 | static const char name_s3c2442[] = "S3C2442"; |
71 | static const char name_s3c2443[] = "S3C2443"; | ||
70 | static const char name_s3c2410a[] = "S3C2410A"; | 72 | static const char name_s3c2410a[] = "S3C2410A"; |
71 | static const char name_s3c2440a[] = "S3C2440A"; | 73 | static 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 | ||
231 | EXPORT_SYMBOL(s3c_device_usbgadget); | 232 | EXPORT_SYMBOL(s3c_device_usbgadget); |
232 | 233 | ||
234 | void __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 | ||
235 | static struct resource s3c_wdt_resource[] = { | 250 | static 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 */ | ||
42 | static void __iomem *dma_base; | ||
43 | static struct kmem_cache *dma_kmem; | ||
44 | |||
45 | static int dma_channels; | ||
46 | |||
47 | struct s3c24xx_dma_selection dma_sel; | ||
48 | |||
49 | /* dma channel state information */ | ||
50 | struct 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 | ||
63 | static inline void | ||
64 | dma_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 | |||
75 | struct 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 | |||
90 | static void | ||
91 | dmadbg_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 | |||
100 | static void | ||
101 | dmadbg_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 | |||
110 | static void | ||
111 | dmadbg_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 | |||
124 | static void | ||
125 | dmadbg_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 | |||
140 | static 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 | |||
147 | static 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 | |||
160 | static void | ||
161 | s3c2410_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 | |||
179 | static int | ||
180 | s3c2410_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 | |||
226 | static inline int | ||
227 | s3c2410_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 | |||
300 | static void | ||
301 | s3c2410_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 | |||
314 | static inline void | ||
315 | s3c2410_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 | |||
333 | static 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 | |||
428 | static int | ||
429 | s3c2410_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 | |||
455 | int 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 | |||
536 | EXPORT_SYMBOL(s3c2410_dma_enqueue); | ||
537 | |||
538 | static inline void | ||
539 | s3c2410_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 | |||
558 | static inline void | ||
559 | s3c2410_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 | |||
599 | static irqreturn_t | ||
600 | s3c2410_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 | |||
728 | static 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 | |||
735 | int 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 | |||
793 | EXPORT_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 | |||
806 | int 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 | |||
847 | EXPORT_SYMBOL(s3c2410_dma_free); | ||
848 | |||
849 | static 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 | |||
883 | void 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 | |||
904 | static 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 | |||
960 | int | ||
961 | s3c2410_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 | |||
997 | int | ||
998 | s3c2410_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 | |||
1030 | EXPORT_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 | |||
1046 | int 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 | |||
1093 | EXPORT_SYMBOL(s3c2410_dma_config); | ||
1094 | |||
1095 | int 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 | |||
1109 | EXPORT_SYMBOL(s3c2410_dma_setflags); | ||
1110 | |||
1111 | |||
1112 | /* do we need to protect the settings of the fields from | ||
1113 | * irq? | ||
1114 | */ | ||
1115 | |||
1116 | int 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 | |||
1130 | EXPORT_SYMBOL(s3c2410_dma_set_opfn); | ||
1131 | |||
1132 | int 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 | |||
1146 | EXPORT_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 | |||
1162 | int 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 | |||
1206 | EXPORT_SYMBOL(s3c2410_dma_devconfig); | ||
1207 | |||
1208 | /* s3c2410_dma_getposition | ||
1209 | * | ||
1210 | * returns the current transfer points for the dma source and destination | ||
1211 | */ | ||
1212 | |||
1213 | int 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 | |||
1229 | EXPORT_SYMBOL(s3c2410_dma_getposition); | ||
1230 | |||
1231 | |||
1232 | /* system device class */ | ||
1233 | |||
1234 | #ifdef CONFIG_PM | ||
1235 | |||
1236 | static 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 | |||
1258 | static 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 | |||
1268 | struct 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 | |||
1276 | static 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 | |||
1283 | int __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 | |||
1293 | core_initcall(s3c24xx_dma_sysclass_init); | ||
1294 | |||
1295 | int __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 | |||
1315 | late_initcall(s3c24xx_dma_sysdev_register); | ||
1316 | |||
1317 | int __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 | |||
1376 | int s3c2410_dma_init(void) | ||
1377 | { | ||
1378 | return s3c24xx_dma_init(4, IRQ_DMA0, 0x40); | ||
1379 | } | ||
1380 | |||
1381 | static inline int is_channel_valid(unsigned int channel) | ||
1382 | { | ||
1383 | return (channel & DMA_CH_VALID); | ||
1384 | } | ||
1385 | |||
1386 | static 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 | |||
1399 | struct 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 | |||
1458 | static int s3c24xx_dma_check_entry(struct s3c24xx_dma_map *map, int ch) | ||
1459 | { | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | int __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 | |||
1484 | int __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 | |||
36 | void 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 | |||
82 | EXPORT_SYMBOL(s3c2410_gpio_cfgpin); | ||
83 | |||
84 | unsigned 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 | |||
101 | EXPORT_SYMBOL(s3c2410_gpio_getcfg); | ||
102 | |||
103 | void 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 | |||
123 | EXPORT_SYMBOL(s3c2410_gpio_pullup); | ||
124 | |||
125 | void 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 | |||
142 | EXPORT_SYMBOL(s3c2410_gpio_setpin); | ||
143 | |||
144 | unsigned 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 | |||
152 | EXPORT_SYMBOL(s3c2410_gpio_getpin); | ||
153 | |||
154 | unsigned 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 | |||
169 | EXPORT_SYMBOL(s3c2410_modify_misccr); | ||
170 | |||
171 | int 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 | |||
188 | EXPORT_SYMBOL(s3c2410_gpio_getirq); | ||
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c new file mode 100644 index 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 | |||
84 | unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL; | ||
85 | unsigned long s3c_irqwake_intmask = 0xffffffffL; | ||
86 | unsigned long s3c_irqwake_eintallow = 0x0000fff0L; | ||
87 | unsigned long s3c_irqwake_eintmask = 0xffffffffL; | ||
88 | |||
89 | int | ||
90 | s3c_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 | |||
108 | static int | ||
109 | s3c_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 | |||
133 | static void | ||
134 | s3c_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 | |||
145 | static inline void | ||
146 | s3c_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 | |||
154 | static inline void | ||
155 | s3c_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 | |||
168 | static void | ||
169 | s3c_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 | |||
183 | struct 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 | |||
191 | static 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 | |||
199 | static void | ||
200 | s3c_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 | |||
211 | static void | ||
212 | s3c_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 | |||
238 | static void | ||
239 | s3c_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 | |||
250 | int | ||
251 | s3c_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 | |||
332 | static 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 | |||
341 | static 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 | |||
360 | static void | ||
361 | s3c_irq_uart0_mask(unsigned int irqno) | ||
362 | { | ||
363 | s3c_irqsub_mask(irqno, INTMSK_UART0, 7); | ||
364 | } | ||
365 | |||
366 | static void | ||
367 | s3c_irq_uart0_unmask(unsigned int irqno) | ||
368 | { | ||
369 | s3c_irqsub_unmask(irqno, INTMSK_UART0); | ||
370 | } | ||
371 | |||
372 | static void | ||
373 | s3c_irq_uart0_ack(unsigned int irqno) | ||
374 | { | ||
375 | s3c_irqsub_maskack(irqno, INTMSK_UART0, 7); | ||
376 | } | ||
377 | |||
378 | static 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 | |||
387 | static void | ||
388 | s3c_irq_uart1_mask(unsigned int irqno) | ||
389 | { | ||
390 | s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3); | ||
391 | } | ||
392 | |||
393 | static void | ||
394 | s3c_irq_uart1_unmask(unsigned int irqno) | ||
395 | { | ||
396 | s3c_irqsub_unmask(irqno, INTMSK_UART1); | ||
397 | } | ||
398 | |||
399 | static void | ||
400 | s3c_irq_uart1_ack(unsigned int irqno) | ||
401 | { | ||
402 | s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3); | ||
403 | } | ||
404 | |||
405 | static 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 | |||
414 | static void | ||
415 | s3c_irq_uart2_mask(unsigned int irqno) | ||
416 | { | ||
417 | s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6); | ||
418 | } | ||
419 | |||
420 | static void | ||
421 | s3c_irq_uart2_unmask(unsigned int irqno) | ||
422 | { | ||
423 | s3c_irqsub_unmask(irqno, INTMSK_UART2); | ||
424 | } | ||
425 | |||
426 | static void | ||
427 | s3c_irq_uart2_ack(unsigned int irqno) | ||
428 | { | ||
429 | s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6); | ||
430 | } | ||
431 | |||
432 | static 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 | |||
441 | static void | ||
442 | s3c_irq_adc_mask(unsigned int irqno) | ||
443 | { | ||
444 | s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9); | ||
445 | } | ||
446 | |||
447 | static void | ||
448 | s3c_irq_adc_unmask(unsigned int irqno) | ||
449 | { | ||
450 | s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT); | ||
451 | } | ||
452 | |||
453 | static void | ||
454 | s3c_irq_adc_ack(unsigned int irqno) | ||
455 | { | ||
456 | s3c_irqsub_ack(irqno, INTMSK_ADCPARENT, 3 << 9); | ||
457 | } | ||
458 | |||
459 | static 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 */ | ||
467 | static 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 | |||
496 | static 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 | |||
535 | static void | ||
536 | s3c_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 | |||
543 | static void | ||
544 | s3c_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 | |||
551 | static void | ||
552 | s3c_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 | |||
559 | static void | ||
560 | s3c_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 | |||
581 | static void | ||
582 | s3c_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 | |||
605 | static 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 | |||
615 | static unsigned long save_extint[3]; | ||
616 | static unsigned long save_eintflt[4]; | ||
617 | static unsigned long save_eintmask; | ||
618 | |||
619 | int 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 | |||
635 | int 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 | |||
661 | void __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 | |||
55 | unsigned long s3c_pm_flags; | ||
56 | |||
57 | #define PFX "s3c24xx-pm: " | ||
58 | |||
59 | static 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 | |||
86 | static 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 | |||
130 | static 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 | |||
144 | extern void printascii(const char *); | ||
145 | |||
146 | void 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 | |||
158 | static 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 | |||
177 | static 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 | |||
194 | static u32 crc_size; /* size needed for the crc block */ | ||
195 | static u32 *crcs; /* allocated over suspend/resume */ | ||
196 | |||
197 | typedef 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 | |||
204 | static 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 | |||
221 | static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg) | ||
222 | { | ||
223 | s3c2410_pm_run_res(&iomem_resource, fn, arg); | ||
224 | } | ||
225 | |||
226 | static 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 | |||
247 | static 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 | |||
260 | static 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 | |||
284 | static 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 | |||
296 | static 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 | |||
307 | static 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 | |||
358 | static 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 | |||
376 | void 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 | |||
392 | void 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 | |||
410 | static 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 | |||
422 | static 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 | |||
442 | static 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 | |||
471 | static 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 | |||
489 | void (*pm_cpu_prep)(void); | ||
490 | void (*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 | |||
499 | static 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 | */ | ||
623 | static 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 | */ | ||
631 | static 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 | */ | ||
639 | static 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 | |||
653 | int __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 | ||
46 | static struct map_desc s3c244x_iodesc[] __initdata = { | 46 | static 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 | |||
62 | ENTRY(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 | ||
80 | resume_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 | ||
96 | s3c2410_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 | |||
108 | ENTRY(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 ] | ||
130 | 1001: | ||
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 | ||
43 | static unsigned long timer_startval; | 43 | static unsigned long timer_startval; |
44 | static unsigned long timer_usec_ticks; | 44 | static unsigned long timer_usec_ticks; |