diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-09-12 12:02:26 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-12 12:02:26 +0100 |
commit | ddd559b13f6d2fe3ad68c4b3f5235fd3c2eae4e3 (patch) | |
tree | d827bca3fc825a0ac33efbcd493713be40fcc812 /arch/arm | |
parent | cf7a2b4fb6a9b86779930a0a123b0df41aa9208f (diff) | |
parent | f17a1f06d2fa93f4825be572622eb02c4894db4e (diff) | |
download | linux-ddd559b13f6d2fe3ad68c4b3f5235fd3c2eae4e3.tar.bz2 |
Merge branch 'devel-stable' into devel
Conflicts:
MAINTAINERS
arch/arm/mm/fault.c
Diffstat (limited to 'arch/arm')
330 files changed, 20139 insertions, 1662 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5d60508472f0..d778a699f577 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -46,10 +46,6 @@ config GENERIC_CLOCKEVENTS_BROADCAST depends on GENERIC_CLOCKEVENTS default y if SMP && !LOCAL_TIMERS -config MMU - bool - default y - config NO_IOPORT bool @@ -126,6 +122,13 @@ config ARCH_HAS_ILOG2_U32 config ARCH_HAS_ILOG2_U64 bool +config ARCH_HAS_CPUFREQ + bool + help + Internal node to signify that the ARCH has CPUFREQ support + and that the relevant menu configurations are displayed for + it. + config GENERIC_HWEIGHT bool default y @@ -188,6 +191,13 @@ source "kernel/Kconfig.freezer" menu "System Type" +config MMU + bool "MMU-based Paged Memory Management Support" + default y + help + Select if you want MMU-based virtualised addressing space + support by paged memory management. If unsure, say 'Y'. + choice prompt "ARM system type" default ARCH_VERSATILE @@ -203,6 +213,7 @@ config ARCH_AAEC2000 config ARCH_INTEGRATOR bool "ARM Ltd. Integrator family" select ARM_AMBA + select ARCH_HAS_CPUFREQ select HAVE_CLK select COMMON_CLKDEV select ICST525 @@ -329,6 +340,20 @@ config ARCH_H720X help This enables support for systems based on the Hynix HMS720x +config ARCH_NOMADIK + bool "STMicroelectronics Nomadik" + select ARM_AMBA + select ARM_VIC + select CPU_ARM926T + select HAVE_CLK + select COMMON_CLKDEV + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB + help + Support for the Nomadik platform by ST-Ericsson + config ARCH_IOP13XX bool "IOP13xx-based" depends on MMU @@ -519,6 +544,7 @@ config ARCH_PXA bool "PXA2xx/PXA3xx-based" depends on MMU select ARCH_MTD_XIP + select ARCH_HAS_CPUFREQ select GENERIC_GPIO select HAVE_CLK select COMMON_CLKDEV @@ -561,6 +587,7 @@ config ARCH_SA1100 select ISA select ARCH_SPARSEMEM_ENABLE select ARCH_MTD_XIP + select ARCH_HAS_CPUFREQ select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -573,6 +600,7 @@ config ARCH_SA1100 config ARCH_S3C2410 bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" select GENERIC_GPIO + select ARCH_HAS_CPUFREQ select HAVE_CLK help Samsung S3C2410X CPU based systems, such as the Simtec Electronics @@ -583,9 +611,18 @@ config ARCH_S3C64XX bool "Samsung S3C64XX" select GENERIC_GPIO select HAVE_CLK + select ARCH_HAS_CPUFREQ help Samsung S3C64XX series based systems +config ARCH_S5PC1XX + bool "Samsung S5PC1XX" + select GENERIC_GPIO + select HAVE_CLK + select CPU_V7 + help + Samsung S5PC1XX series based systems + config ARCH_SHARK bool "Shark" select CPU_SA110 @@ -642,6 +679,7 @@ config ARCH_OMAP select GENERIC_GPIO select HAVE_CLK select ARCH_REQUIRE_GPIOLIB + select ARCH_HAS_CPUFREQ select GENERIC_TIME select GENERIC_CLOCKEVENTS help @@ -707,6 +745,7 @@ source "arch/arm/mach-kirkwood/Kconfig" source "arch/arm/plat-s3c24xx/Kconfig" source "arch/arm/plat-s3c64xx/Kconfig" source "arch/arm/plat-s3c/Kconfig" +source "arch/arm/plat-s5pc1xx/Kconfig" if ARCH_S3C2410 source "arch/arm/mach-s3c2400/Kconfig" @@ -724,6 +763,10 @@ endif source "arch/arm/plat-stmp3xxx/Kconfig" +if ARCH_S5PC1XX +source "arch/arm/mach-s5pc100/Kconfig" +endif + source "arch/arm/mach-lh7a40x/Kconfig" source "arch/arm/mach-h720x/Kconfig" @@ -738,6 +781,8 @@ source "arch/arm/mach-at91/Kconfig" source "arch/arm/plat-mxc/Kconfig" +source "arch/arm/mach-nomadik/Kconfig" + source "arch/arm/mach-netx/Kconfig" source "arch/arm/mach-ns9xxx/Kconfig" @@ -986,18 +1031,7 @@ config LOCAL_TIMERS accounting to be spread across the timer interval, preventing a "thundering herd" at every timer tick. -config PREEMPT - bool "Preemptible Kernel (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This option reduces the latency of the kernel when reacting to - real-time or interactive events by allowing a low priority process to - be preempted even if it is in kernel mode executing a system call. - This allows applications to run more reliably even when the system is - under load. - - Say Y here if you are building a kernel for a desktop, embedded - or real-time system. Say N if you are unsure. +source kernel/Kconfig.preempt config HZ int @@ -1007,6 +1041,21 @@ config HZ default AT91_TIMER_HZ if ARCH_AT91 default 100 +config THUMB2_KERNEL + bool "Compile the kernel in Thumb-2 mode" + depends on CPU_V7 && EXPERIMENTAL + select AEABI + select ARM_ASM_UNIFIED + help + By enabling this option, the kernel will be compiled in + Thumb-2 mode. A compiler/assembler that understand the unified + ARM-Thumb syntax is needed. + + If unsure, say N. + +config ARM_ASM_UNIFIED + bool + config AEABI bool "Use the ARM EABI to compile the kernel" help @@ -1270,7 +1319,7 @@ endmenu menu "CPU Power Management" -if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_PXA || ARCH_S3C64XX) +if ARCH_HAS_CPUFREQ source "drivers/cpufreq/Kconfig" @@ -1305,6 +1354,52 @@ config CPU_FREQ_S3C64XX bool "CPUfreq support for Samsung S3C64XX CPUs" depends on CPU_FREQ && CPU_S3C6410 +config CPU_FREQ_S3C + bool + help + Internal configuration node for common cpufreq on Samsung SoC + +config CPU_FREQ_S3C24XX + bool "CPUfreq driver for Samsung S3C24XX series CPUs" + depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL + select CPU_FREQ_S3C + help + This enables the CPUfreq driver for the Samsung S3C24XX family + of CPUs. + + For details, take a look at <file:Documentation/cpu-freq>. + + If in doubt, say N. + +config CPU_FREQ_S3C24XX_PLL + bool "Support CPUfreq changing of PLL frequency" + depends on CPU_FREQ_S3C24XX && EXPERIMENTAL + help + Compile in support for changing the PLL frequency from the + S3C24XX series CPUfreq driver. The PLL takes time to settle + after a frequency change, so by default it is not enabled. + + This also means that the PLL tables for the selected CPU(s) will + be built which may increase the size of the kernel image. + +config CPU_FREQ_S3C24XX_DEBUG + bool "Debug CPUfreq Samsung driver core" + depends on CPU_FREQ_S3C24XX + help + Enable s3c_freq_dbg for the Samsung S3C CPUfreq core + +config CPU_FREQ_S3C24XX_IODEBUG + bool "Debug CPUfreq Samsung driver IO timing" + depends on CPU_FREQ_S3C24XX + help + Enable s3c_freq_iodbg for the Samsung S3C CPUfreq core + +config CPU_FREQ_S3C24XX_DEBUGFS + bool "Export debugfs for CPUFreq" + depends on CPU_FREQ_S3C24XX && DEBUG_FS + help + Export status information via debugfs. + endif source "drivers/cpuidle/Kconfig" @@ -1406,107 +1501,7 @@ endmenu source "net/Kconfig" -menu "Device Drivers" - -source "drivers/base/Kconfig" - -source "drivers/connector/Kconfig" - -if ALIGNMENT_TRAP || !CPU_CP15_MMU -source "drivers/mtd/Kconfig" -endif - -source "drivers/parport/Kconfig" - -source "drivers/pnp/Kconfig" - -source "drivers/block/Kconfig" - -# misc before ide - BLK_DEV_SGIIOC4 depends on SGI_IOC4 - -source "drivers/misc/Kconfig" - -source "drivers/ide/Kconfig" - -source "drivers/scsi/Kconfig" - -source "drivers/ata/Kconfig" - -source "drivers/md/Kconfig" - -source "drivers/message/fusion/Kconfig" - -source "drivers/ieee1394/Kconfig" - -source "drivers/message/i2o/Kconfig" - -source "drivers/net/Kconfig" - -source "drivers/isdn/Kconfig" - -# input before char - char/joystick depends on it. As does USB. - -source "drivers/input/Kconfig" - -source "drivers/char/Kconfig" - -source "drivers/i2c/Kconfig" - -source "drivers/spi/Kconfig" - -source "drivers/gpio/Kconfig" - -source "drivers/w1/Kconfig" - -source "drivers/power/Kconfig" - -source "drivers/hwmon/Kconfig" - -source "drivers/thermal/Kconfig" - -source "drivers/watchdog/Kconfig" - -source "drivers/ssb/Kconfig" - -#source "drivers/l3/Kconfig" - -source "drivers/mfd/Kconfig" - -source "drivers/media/Kconfig" - -source "drivers/video/Kconfig" - -source "sound/Kconfig" - -source "drivers/hid/Kconfig" - -source "drivers/usb/Kconfig" - -source "drivers/uwb/Kconfig" - -source "drivers/mmc/Kconfig" - -source "drivers/memstick/Kconfig" - -source "drivers/accessibility/Kconfig" - -source "drivers/leds/Kconfig" - -source "drivers/rtc/Kconfig" - -source "drivers/dma/Kconfig" - -source "drivers/dca/Kconfig" - -source "drivers/auxdisplay/Kconfig" - -source "drivers/regulator/Kconfig" - -source "drivers/uio/Kconfig" - -source "drivers/staging/Kconfig" - -endmenu +source "drivers/Kconfig" source "fs/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index a89e4734b8f0..1a6f70e52921 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -8,6 +8,7 @@ source "lib/Kconfig.debug" # n, but then RMK will have to kill you ;). config FRAME_POINTER bool + depends on !THUMB2_KERNEL default y if !ARM_UNWIND help If you say N here, the resulting kernel will be slightly smaller and diff --git a/arch/arm/Makefile b/arch/arm/Makefile index b9ae98b88a7e..7350557a81e0 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -93,9 +93,16 @@ ifeq ($(CONFIG_ARM_UNWIND),y) CFLAGS_ABI +=-funwind-tables endif +ifeq ($(CONFIG_THUMB2_KERNEL),y) +AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=thumb,-Wa$(comma)-mauto-it) +AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W) +CFLAGS_THUMB2 :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN) +AFLAGS_THUMB2 :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb +endif + # Need -Uarm for gcc < 3.x -KBUILD_CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm -KBUILD_AFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -msoft-float +KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm +KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float CHECKFLAGS += -D__arm__ @@ -136,8 +143,10 @@ machine-$(CONFIG_ARCH_MSM) := msm machine-$(CONFIG_ARCH_MV78XX0) := mv78xx0 machine-$(CONFIG_ARCH_MX1) := mx1 machine-$(CONFIG_ARCH_MX2) := mx2 +machine-$(CONFIG_ARCH_MX25) := mx25 machine-$(CONFIG_ARCH_MX3) := mx3 machine-$(CONFIG_ARCH_NETX) := netx +machine-$(CONFIG_ARCH_NOMADIK) := nomadik machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx machine-$(CONFIG_ARCH_OMAP1) := omap1 machine-$(CONFIG_ARCH_OMAP2) := omap2 @@ -151,6 +160,7 @@ machine-$(CONFIG_ARCH_RPC) := rpc machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443 machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 machine-$(CONFIG_ARCH_S3C64XX) := s3c6400 s3c6410 +machine-$(CONFIG_ARCH_S5PC1XX) := s5pc100 machine-$(CONFIG_ARCH_SA1100) := sa1100 machine-$(CONFIG_ARCH_SHARK) := shark machine-$(CONFIG_ARCH_STMP378X) := stmp378x @@ -159,6 +169,7 @@ machine-$(CONFIG_ARCH_U300) := u300 machine-$(CONFIG_ARCH_VERSATILE) := versatile machine-$(CONFIG_ARCH_W90X900) := w90x900 machine-$(CONFIG_FOOTBRIDGE) := footbridge +machine-$(CONFIG_ARCH_MXC91231) := mxc91231 # Platform directory name. This list is sorted alphanumerically # by CONFIG_* macro name. @@ -169,6 +180,7 @@ plat-$(CONFIG_PLAT_ORION) := orion plat-$(CONFIG_PLAT_PXA) := pxa plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx s3c plat-$(CONFIG_PLAT_S3C64XX) := s3c64xx s3c +plat-$(CONFIG_PLAT_S5PC1XX) := s5pc1xx s3c plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx ifeq ($(CONFIG_ARCH_EBSA110),y) diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index da226abce2d0..4a590f4113e2 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -61,7 +61,7 @@ endif quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \ - -C none -a $(LOADADDR) -e $(LOADADDR) \ + -C none -a $(LOADADDR) -e $(STARTADDR) \ -n 'Linux-$(KERNELRELEASE)' -d $< $@ ifeq ($(CONFIG_ZBOOT_ROM),y) @@ -70,6 +70,13 @@ else $(obj)/uImage: LOADADDR=$(ZRELADDR) endif +ifeq ($(CONFIG_THUMB2_KERNEL),y) +# Set bit 0 to 1 so that "mov pc, rx" switches to Thumb-2 mode +$(obj)/uImage: STARTADDR=$(shell echo $(LOADADDR) | sed -e "s/.$$/1/") +else +$(obj)/uImage: STARTADDR=$(LOADADDR) +endif + $(obj)/uImage: $(obj)/zImage FORCE $(call if_changed,uimage) @echo ' Image $@ is ready' diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 4515728c5345..fa6fbf45cf3b 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -140,7 +140,8 @@ start: tst r2, #3 @ not user? bne not_angel mov r0, #0x17 @ angel_SWIreason_EnterSVC - swi 0x123456 @ angel_SWI_ARM + ARM( swi 0x123456 ) @ angel_SWI_ARM + THUMB( svc 0xab ) @ angel_SWI_THUMB not_angel: mrs r2, cpsr @ turn off interrupts to orr r2, r2, #0xc0 @ prevent angel from running @@ -161,7 +162,9 @@ not_angel: .text adr r0, LC0 - ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} + ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} ) + THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, ip} ) + THUMB( ldr sp, [r0, #28] ) subs r0, r0, r1 @ calculate the delta offset @ if delta is zero, we are @@ -263,22 +266,25 @@ not_relocated: mov r0, #0 * r6 = processor ID * r7 = architecture ID * r8 = atags pointer - * r9-r14 = corrupted + * r9-r12,r14 = corrupted */ add r1, r5, r0 @ end of decompressed kernel adr r2, reloc_start ldr r3, LC1 add r3, r2, r3 -1: ldmia r2!, {r9 - r14} @ copy relocation code - stmia r1!, {r9 - r14} - ldmia r2!, {r9 - r14} - stmia r1!, {r9 - r14} +1: ldmia r2!, {r9 - r12, r14} @ copy relocation code + stmia r1!, {r9 - r12, r14} + ldmia r2!, {r9 - r12, r14} + stmia r1!, {r9 - r12, r14} cmp r2, r3 blo 1b - add sp, r1, #128 @ relocate the stack + mov sp, r1 + add sp, sp, #128 @ relocate the stack bl cache_clean_flush - add pc, r5, r0 @ call relocation code + ARM( add pc, r5, r0 ) @ call relocation code + THUMB( add r12, r5, r0 ) + THUMB( mov pc, r12 ) @ call relocation code /* * We're not in danger of overwriting ourselves. Do this the simple way. @@ -291,6 +297,7 @@ wont_overwrite: mov r0, r4 bl decompress_kernel b call_kernel + .align 2 .type LC0, #object LC0: .word LC0 @ r1 .word __bss_start @ r2 @@ -431,6 +438,7 @@ ENDPROC(__setup_mmu) __armv4_mmu_cache_on: mov r12, lr +#ifdef CONFIG_MMU bl __setup_mmu mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer @@ -444,10 +452,12 @@ __armv4_mmu_cache_on: bl __common_mmu_cache_on mov r0, #0 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs +#endif mov pc, r12 __armv7_mmu_cache_on: mov r12, lr +#ifdef CONFIG_MMU mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0 tst r11, #0xf @ VMSA blne __setup_mmu @@ -455,9 +465,11 @@ __armv7_mmu_cache_on: mcr p15, 0, r0, c7, c10, 4 @ drain write buffer tst r11, #0xf @ VMSA mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs +#endif mrc p15, 0, r0, c1, c0, 0 @ read control reg orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x003c @ write buffer +#ifdef CONFIG_MMU #ifdef CONFIG_CPU_ENDIAN_BE8 orr r0, r0, #1 << 25 @ big-endian page tables #endif @@ -465,6 +477,7 @@ __armv7_mmu_cache_on: movne r1, #-1 mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer mcrne p15, 0, r1, c3, c0, 0 @ load domain access control +#endif mcr p15, 0, r0, c1, c0, 0 @ load control register mrc p15, 0, r0, c1, c0, 0 @ and read it back mov r0, #0 @@ -498,6 +511,7 @@ __arm6_mmu_cache_on: mov pc, r12 __common_mmu_cache_on: +#ifndef CONFIG_THUMB2_KERNEL #ifndef DEBUG orr r0, r0, #0x000d @ Write buffer, mmu #endif @@ -509,6 +523,7 @@ __common_mmu_cache_on: 1: mcr p15, 0, r0, c1, c0, 0 @ load control register mrc p15, 0, r0, c1, c0, 0 @ and read it back to sub pc, lr, r0, lsr #32 @ properly flush pipeline +#endif /* * All code following this line is relocatable. It is relocated by @@ -522,7 +537,7 @@ __common_mmu_cache_on: * r6 = processor ID * r7 = architecture ID * r8 = atags pointer - * r9-r14 = corrupted + * r9-r12,r14 = corrupted */ .align 5 reloc_start: add r9, r5, r0 @@ -531,13 +546,14 @@ reloc_start: add r9, r5, r0 mov r1, r4 1: .rept 4 - ldmia r5!, {r0, r2, r3, r10 - r14} @ relocate kernel - stmia r1!, {r0, r2, r3, r10 - r14} + ldmia r5!, {r0, r2, r3, r10 - r12, r14} @ relocate kernel + stmia r1!, {r0, r2, r3, r10 - r12, r14} .endr cmp r5, r9 blo 1b - add sp, r1, #128 @ relocate the stack + mov sp, r1 + add sp, sp, #128 @ relocate the stack debug_reloc_end call_kernel: bl cache_clean_flush @@ -571,7 +587,9 @@ call_cache_fn: adr r12, proc_types ldr r2, [r12, #4] @ get mask eor r1, r1, r6 @ (real ^ match) tst r1, r2 @ & mask - addeq pc, r12, r3 @ call cache function + ARM( addeq pc, r12, r3 ) @ call cache function + THUMB( addeq r12, r3 ) + THUMB( moveq pc, r12 ) @ call cache function add r12, r12, #4*5 b 1b @@ -589,13 +607,15 @@ call_cache_fn: adr r12, proc_types * methods. Writeback caches _must_ have the flush method * defined. */ + .align 2 .type proc_types,#object proc_types: .word 0x41560600 @ ARM6/610 .word 0xffffffe0 - b __arm6_mmu_cache_off @ works, but slow - b __arm6_mmu_cache_off + W(b) __arm6_mmu_cache_off @ works, but slow + W(b) __arm6_mmu_cache_off mov pc, lr + THUMB( nop ) @ b __arm6_mmu_cache_on @ untested @ b __arm6_mmu_cache_off @ b __armv3_mmu_cache_flush @@ -603,76 +623,84 @@ proc_types: .word 0x00000000 @ old ARM ID .word 0x0000f000 mov pc, lr + THUMB( nop ) mov pc, lr + THUMB( nop ) mov pc, lr + THUMB( nop ) .word 0x41007000 @ ARM7/710 .word 0xfff8fe00 - b __arm7_mmu_cache_off - b __arm7_mmu_cache_off + W(b) __arm7_mmu_cache_off + W(b) __arm7_mmu_cache_off mov pc, lr + THUMB( nop ) .word 0x41807200 @ ARM720T (writethrough) .word 0xffffff00 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off mov pc, lr + THUMB( nop ) .word 0x41007400 @ ARM74x .word 0xff00ff00 - b __armv3_mpu_cache_on - b __armv3_mpu_cache_off - b __armv3_mpu_cache_flush + W(b) __armv3_mpu_cache_on + W(b) __armv3_mpu_cache_off + W(b) __armv3_mpu_cache_flush .word 0x41009400 @ ARM94x .word 0xff00ff00 - b __armv4_mpu_cache_on - b __armv4_mpu_cache_off - b __armv4_mpu_cache_flush + W(b) __armv4_mpu_cache_on + W(b) __armv4_mpu_cache_off + W(b) __armv4_mpu_cache_flush .word 0x00007000 @ ARM7 IDs .word 0x0000f000 mov pc, lr + THUMB( nop ) mov pc, lr + THUMB( nop ) mov pc, lr + THUMB( nop ) @ Everything from here on will be the new ID system. .word 0x4401a100 @ sa110 / sa1100 .word 0xffffffe0 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv4_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_flush .word 0x6901b110 @ sa1110 .word 0xfffffff0 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv4_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_flush .word 0x56056930 .word 0xff0ffff0 @ PXA935 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv4_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_flush .word 0x56158000 @ PXA168 .word 0xfffff000 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv5tej_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv5tej_mmu_cache_flush .word 0x56056930 .word 0xff0ffff0 @ PXA935 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv4_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_flush .word 0x56050000 @ Feroceon .word 0xff0f0000 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv5tej_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv5tej_mmu_cache_flush #ifdef CONFIG_CPU_FEROCEON_OLD_ID /* this conflicts with the standard ARMv5TE entry */ @@ -685,47 +713,50 @@ proc_types: .word 0x66015261 @ FA526 .word 0xff01fff1 - b __fa526_cache_on - b __armv4_mmu_cache_off - b __fa526_cache_flush + W(b) __fa526_cache_on + W(b) __armv4_mmu_cache_off + W(b) __fa526_cache_flush @ These match on the architecture ID .word 0x00020000 @ ARMv4T .word 0x000f0000 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv4_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_flush .word 0x00050000 @ ARMv5TE .word 0x000f0000 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv4_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_flush .word 0x00060000 @ ARMv5TEJ .word 0x000f0000 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv5tej_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv4_mmu_cache_flush .word 0x0007b000 @ ARMv6 .word 0x000ff000 - b __armv4_mmu_cache_on - b __armv4_mmu_cache_off - b __armv6_mmu_cache_flush + W(b) __armv4_mmu_cache_on + W(b) __armv4_mmu_cache_off + W(b) __armv6_mmu_cache_flush .word 0x000f0000 @ new CPU Id .word 0x000f0000 - b __armv7_mmu_cache_on - b __armv7_mmu_cache_off - b __armv7_mmu_cache_flush + W(b) __armv7_mmu_cache_on + W(b) __armv7_mmu_cache_off + W(b) __armv7_mmu_cache_flush .word 0 @ unrecognised type .word 0 mov pc, lr + THUMB( nop ) mov pc, lr + THUMB( nop ) mov pc, lr + THUMB( nop ) .size proc_types, . - proc_types @@ -760,22 +791,30 @@ __armv3_mpu_cache_off: mov pc, lr __armv4_mmu_cache_off: +#ifdef CONFIG_MMU mrc p15, 0, r0, c1, c0 bic r0, r0, #0x000d mcr p15, 0, r0, c1, c0 @ turn MMU and cache off mov r0, #0 mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 +#endif mov pc, lr __armv7_mmu_cache_off: mrc p15, 0, r0, c1, c0 +#ifdef CONFIG_MMU bic r0, r0, #0x000d +#else + bic r0, r0, #0x000c +#endif mcr p15, 0, r0, c1, c0 @ turn MMU and cache off mov r12, lr bl __armv7_mmu_cache_flush mov r0, #0 +#ifdef CONFIG_MMU mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB +#endif mcr p15, 0, r0, c7, c5, 6 @ invalidate BTC mcr p15, 0, r0, c7, c10, 4 @ DSB mcr p15, 0, r0, c7, c5, 4 @ ISB @@ -852,7 +891,7 @@ __armv7_mmu_cache_flush: b iflush hierarchical: mcr p15, 0, r10, c7, c10, 5 @ DMB - stmfd sp!, {r0-r5, r7, r9, r11} + stmfd sp!, {r0-r7, r9-r11} mrc p15, 1, r0, c0, c0, 1 @ read clidr ands r3, r0, #0x7000000 @ extract loc from clidr mov r3, r3, lsr #23 @ left align loc bit field @@ -877,8 +916,12 @@ loop1: loop2: mov r9, r4 @ create working copy of max way size loop3: - orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 - orr r11, r11, r7, lsl r2 @ factor index number into r11 + ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 + ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r9, r5 ) + THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 + THUMB( lsl r6, r7, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way subs r9, r9, #1 @ decrement the way bge loop3 @@ -889,7 +932,7 @@ skip: cmp r3, r10 bgt loop1 finished: - ldmfd sp!, {r0-r5, r7, r9, r11} + ldmfd sp!, {r0-r7, r9-r11} mov r10, #0 @ swith back to cache level 0 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr iflush: @@ -923,9 +966,13 @@ __armv4_mmu_cache_flush: mov r11, #8 mov r11, r11, lsl r3 @ cache line size in bytes no_cache_id: - bic r1, pc, #63 @ align to longest cache line + mov r1, pc + bic r1, r1, #63 @ align to longest cache line add r2, r1, r2 -1: ldr r3, [r1], r11 @ s/w flush D cache +1: + ARM( ldr r3, [r1], r11 ) @ s/w flush D cache + THUMB( ldr r3, [r1] ) @ s/w flush D cache + THUMB( add r1, r1, r11 ) teq r1, r2 bne 1b @@ -945,6 +992,7 @@ __armv3_mpu_cache_flush: * memory, which again must be relocatable. */ #ifdef DEBUG + .align 2 .type phexbuf,#object phexbuf: .space 12 .size phexbuf, . - phexbuf diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index 6ed89836e908..920ced0b73c5 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -22,10 +22,20 @@ #include <linux/list.h> #include <linux/io.h> #include <linux/sysdev.h> +#include <linux/amba/bus.h> #include <asm/mach/irq.h> #include <asm/hardware/vic.h> +static void vic_ack_irq(unsigned int irq) +{ + void __iomem *base = get_irq_chip_data(irq); + irq &= 31; + writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); + /* moreover, clear the soft-triggered, in case it was the reason */ + writel(1 << irq, base + VIC_INT_SOFT_CLEAR); +} + static void vic_mask_irq(unsigned int irq) { void __iomem *base = get_irq_chip_data(irq); @@ -253,12 +263,16 @@ static inline void vic_pm_register(void __iomem *base, unsigned int irq, u32 arg static struct irq_chip vic_chip = { .name = "VIC", - .ack = vic_mask_irq, + .ack = vic_ack_irq, .mask = vic_mask_irq, .unmask = vic_unmask_irq, .set_wake = vic_set_wake, }; +/* The PL190 cell from ARM has been modified by ST, so handle both here */ +static void vik_init_st(void __iomem *base, unsigned int irq_start, + u32 vic_sources); + /** * vic_init - initialise a vectored interrupt controller * @base: iomem base address @@ -270,6 +284,28 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources) { unsigned int i; + u32 cellid = 0; + enum amba_vendor vendor; + + /* Identify which VIC cell this one is, by reading the ID */ + for (i = 0; i < 4; i++) { + u32 addr = ((u32)base & PAGE_MASK) + 0xfe0 + (i * 4); + cellid |= (readl(addr) & 0xff) << (8 * i); + } + vendor = (cellid >> 12) & 0xff; + printk(KERN_INFO "VIC @%p: id 0x%08x, vendor 0x%02x\n", + base, cellid, vendor); + + switch(vendor) { + case AMBA_VENDOR_ST: + vik_init_st(base, irq_start, vic_sources); + return; + default: + printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); + /* fall through */ + case AMBA_VENDOR_ARM: + break; + } /* Disable all interrupts initially. */ @@ -306,3 +342,60 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, vic_pm_register(base, irq_start, resume_sources); } + +/* + * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. + * The original cell has 32 interrupts, while the modified one has 64, + * replocating two blocks 0x00..0x1f in 0x20..0x3f. In that case + * the probe function is called twice, with base set to offset 000 + * and 020 within the page. We call this "second block". + */ +static void __init vik_init_st(void __iomem *base, unsigned int irq_start, + u32 vic_sources) +{ + unsigned int i; + int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; + + /* Disable all interrupts initially. */ + + writel(0, base + VIC_INT_SELECT); + writel(0, base + VIC_INT_ENABLE); + writel(~0, base + VIC_INT_ENABLE_CLEAR); + writel(0, base + VIC_IRQ_STATUS); + writel(0, base + VIC_ITCR); + writel(~0, base + VIC_INT_SOFT_CLEAR); + + /* + * Make sure we clear all existing interrupts. The vector registers + * in this cell are after the second block of general registers, + * so we can address them using standard offsets, but only from + * the second base address, which is 0x20 in the page + */ + if (vic_2nd_block) { + writel(0, base + VIC_PL190_VECT_ADDR); + for (i = 0; i < 19; i++) { + unsigned int value; + + value = readl(base + VIC_PL190_VECT_ADDR); + writel(value, base + VIC_PL190_VECT_ADDR); + } + /* ST has 16 vectors as well, but we don't enable them by now */ + for (i = 0; i < 16; i++) { + void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); + writel(0, reg); + } + + writel(32, base + VIC_PL190_DEF_VECT_ADDR); + } + + for (i = 0; i < 32; i++) { + if (vic_sources & (1 << i)) { + unsigned int irq = irq_start + i; + + set_irq_chip(irq, &vic_chip); + set_irq_chip_data(irq, base); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } +} diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig new file mode 100644 index 000000000000..9bb45b932f04 --- /dev/null +++ b/arch/arm/configs/nhk8815_defconfig @@ -0,0 +1,1316 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.30 +# Tue Jun 23 22:57:16 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Performance Counters +# +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_FREEZER=y + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +CONFIG_ARCH_NOMADIK=y +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set + +# +# Nomadik boards +# +CONFIG_MACH_NOMADIK_8815NHK=y +CONFIG_NOMADIK_8815=y +CONFIG_I2C_BITBANG_8815NHK=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_NOIFAR=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_OUTER_CACHE=y +CONFIG_CACHE_L2X0=y +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +CONFIG_NET_IPIP=y +CONFIG_NET_IPGRE=y +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +# CONFIG_BT_HCIUART_LL is not set +CONFIG_BT_HCIVHCI=m +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +CONFIG_MAC80211_DEFAULT_PS_VALUE=0 +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_TESTS=m +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +CONFIG_MTD_NAND_NOMADIK=y +CONFIG_MTD_ONENAND=y +CONFIG_MTD_ONENAND_VERIFY_WRITE=y +CONFIG_MTD_ONENAND_GENERIC=y +# CONFIG_MTD_ONENAND_OTP is not set +# CONFIG_MTD_ONENAND_2X_PROGRAM is not set +# CONFIG_MTD_ONENAND_SIM is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=y +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +# CONFIG_PPPOL2TP is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=m +CONFIG_NETCONSOLE=m +# CONFIG_NETCONSOLE_DYNAMIC is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_DEBUG_GPIO=y +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_PL061 is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +# CONFIG_HID_APPLE is not set +# CONFIG_HID_WACOM is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V4 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=y +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/arch/arm/configs/s5pc100_defconfig b/arch/arm/configs/s5pc100_defconfig new file mode 100644 index 000000000000..b0d7d3d3a5e3 --- /dev/null +++ b/arch/arm/configs/s5pc100_defconfig @@ -0,0 +1,892 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.30 +# Wed Jul 1 15:53:07 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_MMU=y +CONFIG_NO_IOPORT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Performance Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +CONFIG_ARCH_S5PC1XX=y +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +CONFIG_PLAT_S3C=y + +# +# Boot options +# +# CONFIG_S3C_BOOT_ERROR_RESET is not set +CONFIG_S3C_BOOT_UART_FORCE_FIFO=y + +# +# Power management +# +CONFIG_S3C_LOWLEVEL_UART_PORT=0 +CONFIG_S3C_GPIO_SPACE=0 +CONFIG_S3C_GPIO_TRACK=y +CONFIG_S3C_GPIO_PULL_UPDOWN=y +CONFIG_PLAT_S5PC1XX=y +CONFIG_CPU_S5PC100_INIT=y +CONFIG_CPU_S5PC100_CLOCK=y +CONFIG_S5PC100_SETUP_I2C0=y +CONFIG_CPU_S5PC100=y +CONFIG_MACH_SMDKC100=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_IFAR=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=cramfs init=/linuxrc console=ttySAC2,115200 mem=128M" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_MG_DISK is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ISL29003 is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=y +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_GPIO is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SAMSUNG=y +CONFIG_SERIAL_SAMSUNG_UARTS=3 +# CONFIG_SERIAL_SAMSUNG_DEBUG is not set +CONFIG_SERIAL_SAMSUNG_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +# CONFIG_HIDRAW is not set +# CONFIG_HID_PID is not set + +# +# Special HID drivers +# +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +CONFIG_MMC=y +CONFIG_MMC_DEBUG=y +CONFIG_MMC_UNSAFE_RESUME=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=y +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PLTFM is not set +# CONFIG_MEMSTICK is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_NEW_LEDS is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_REGULATOR is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set +CONFIG_GENERIC_ACL=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +CONFIG_ROMFS_FS=y +CONFIG_ROMFS_BACKED_BY_BLOCK=y +# CONFIG_ROMFS_BACKED_BY_MTD is not set +# CONFIG_ROMFS_BACKED_BY_BOTH is not set +CONFIG_ROMFS_ON_BLOCK=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NILFS2_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_RT_MUTEXES=y +CONFIG_DEBUG_PI_LIST=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARM_UNWIND=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_STACK_USAGE is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set +CONFIG_DEBUG_S3C_PORT=y +CONFIG_DEBUG_S3C_UART=0 + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/u300_defconfig b/arch/arm/configs/u300_defconfig index 4762d9001298..7d61ae6e75da 100644 --- a/arch/arm/configs/u300_defconfig +++ b/arch/arm/configs/u300_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.31-rc1 -# Thu Jul 2 00:16:59 2009 +# Linux kernel version: 2.6.31-rc3 +# Thu Jul 16 23:36:10 2009 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y @@ -9,7 +9,6 @@ CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_MMU=y -CONFIG_HAVE_TCM=y CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -113,7 +112,7 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_BLOCK=y -CONFIG_LBDAF=y +# CONFIG_LBDAF is not set # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set @@ -542,13 +541,14 @@ CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_SUNKBD is not set # CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_LM8323 is not set -# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set @@ -911,7 +911,6 @@ CONFIG_REGULATOR=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set CONFIG_FILE_LOCKING=y @@ -1122,7 +1121,6 @@ CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC32 is not set # CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set -CONFIG_GENERIC_ALLOCATOR=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 15f8a092b700..00f46d9ce299 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -74,23 +74,56 @@ * Enable and disable interrupts */ #if __LINUX_ARM_ARCH__ >= 6 - .macro disable_irq + .macro disable_irq_notrace cpsid i .endm - .macro enable_irq + .macro enable_irq_notrace cpsie i .endm #else - .macro disable_irq + .macro disable_irq_notrace msr cpsr_c, #PSR_I_BIT | SVC_MODE .endm - .macro enable_irq + .macro enable_irq_notrace msr cpsr_c, #SVC_MODE .endm #endif + .macro asm_trace_hardirqs_off +#if defined(CONFIG_TRACE_IRQFLAGS) + stmdb sp!, {r0-r3, ip, lr} + bl trace_hardirqs_off + ldmia sp!, {r0-r3, ip, lr} +#endif + .endm + + .macro asm_trace_hardirqs_on_cond, cond +#if defined(CONFIG_TRACE_IRQFLAGS) + /* + * actually the registers should be pushed and pop'd conditionally, but + * after bl the flags are certainly clobbered + */ + stmdb sp!, {r0-r3, ip, lr} + bl\cond trace_hardirqs_on + ldmia sp!, {r0-r3, ip, lr} +#endif + .endm + + .macro asm_trace_hardirqs_on + asm_trace_hardirqs_on_cond al + .endm + + .macro disable_irq + disable_irq_notrace + asm_trace_hardirqs_off + .endm + + .macro enable_irq + asm_trace_hardirqs_on + enable_irq_notrace + .endm /* * Save the current IRQ state and disable IRQs. Note that this macro * assumes FIQs are enabled, and that the processor is in SVC mode. @@ -104,10 +137,16 @@ * Restore interrupt state previously stored in a register. We don't * guarantee that this will preserve the flags. */ - .macro restore_irqs, oldcpsr + .macro restore_irqs_notrace, oldcpsr msr cpsr_c, \oldcpsr .endm + .macro restore_irqs, oldcpsr + tst \oldcpsr, #PSR_I_BIT + asm_trace_hardirqs_on_cond eq + restore_irqs_notrace \oldcpsr + .endm + #define USER(x...) \ 9999: x; \ .section __ex_table,"a"; \ @@ -127,3 +166,87 @@ #endif #endif .endm + +#ifdef CONFIG_THUMB2_KERNEL + .macro setmode, mode, reg + mov \reg, #\mode + msr cpsr_c, \reg + .endm +#else + .macro setmode, mode, reg + msr cpsr_c, #\mode + .endm +#endif + +/* + * STRT/LDRT access macros with ARM and Thumb-2 variants + */ +#ifdef CONFIG_THUMB2_KERNEL + + .macro usraccoff, instr, reg, ptr, inc, off, cond, abort +9999: + .if \inc == 1 + \instr\cond\()bt \reg, [\ptr, #\off] + .elseif \inc == 4 + \instr\cond\()t \reg, [\ptr, #\off] + .else + .error "Unsupported inc macro argument" + .endif + + .section __ex_table,"a" + .align 3 + .long 9999b, \abort + .previous + .endm + + .macro usracc, instr, reg, ptr, inc, cond, rept, abort + @ explicit IT instruction needed because of the label + @ introduced by the USER macro + .ifnc \cond,al + .if \rept == 1 + itt \cond + .elseif \rept == 2 + ittt \cond + .else + .error "Unsupported rept macro argument" + .endif + .endif + + @ Slightly optimised to avoid incrementing the pointer twice + usraccoff \instr, \reg, \ptr, \inc, 0, \cond, \abort + .if \rept == 2 + usraccoff \instr, \reg, \ptr, \inc, 4, \cond, \abort + .endif + + add\cond \ptr, #\rept * \inc + .endm + +#else /* !CONFIG_THUMB2_KERNEL */ + + .macro usracc, instr, reg, ptr, inc, cond, rept, abort + .rept \rept +9999: + .if \inc == 1 + \instr\cond\()bt \reg, [\ptr], #\inc + .elseif \inc == 4 + \instr\cond\()t \reg, [\ptr], #\inc + .else + .error "Unsupported inc macro argument" + .endif + + .section __ex_table,"a" + .align 3 + .long 9999b, \abort + .previous + .endr + .endm + +#endif /* CONFIG_THUMB2_KERNEL */ + + .macro strusr, reg, ptr, inc, cond=al, rept=1, abort=9001f + usracc str, \reg, \ptr, \inc, \cond, \rept, \abort + .endm + + .macro ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f + usracc ldr, \reg, \ptr, \inc, \cond, \rept, \abort + .endm diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h index c207504de84d..c3b911ee9151 100644 --- a/arch/arm/include/asm/elf.h +++ b/arch/arm/include/asm/elf.h @@ -55,6 +55,9 @@ typedef struct user_fp elf_fpregset_t; #define R_ARM_MOVW_ABS_NC 43 #define R_ARM_MOVT_ABS 44 +#define R_ARM_THM_CALL 10 +#define R_ARM_THM_JUMP24 30 + /* * These are used to set parameters in the core dumps. */ diff --git a/arch/arm/include/asm/ftrace.h b/arch/arm/include/asm/ftrace.h index d74265cffd86..103f7ee97313 100644 --- a/arch/arm/include/asm/ftrace.h +++ b/arch/arm/include/asm/ftrace.h @@ -7,6 +7,7 @@ #ifndef __ASSEMBLY__ extern void mcount(void); +extern void __gnu_mcount_nc(void); #endif #endif diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h index 9ee743b95de8..bfcc15929a7f 100644 --- a/arch/arm/include/asm/futex.h +++ b/arch/arm/include/asm/futex.h @@ -99,6 +99,7 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" "1: ldrt %0, [%3]\n" " teq %0, %1\n" + " it eq @ explicit IT needed for the 2b label\n" "2: streqt %2, [%3]\n" "3:\n" " .section __ex_table,\"a\"\n" diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 85763db87449..376be1a62866 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -44,7 +44,13 @@ * The module space lives between the addresses given by TASK_SIZE * and PAGE_OFFSET - it must be within 32MB of the kernel text. */ +#ifndef CONFIG_THUMB2_KERNEL #define MODULES_VADDR (PAGE_OFFSET - 16*1024*1024) +#else +/* smaller range for Thumb-2 symbols relocation (2^24)*/ +#define MODULES_VADDR (PAGE_OFFSET - 8*1024*1024) +#endif + #if TASK_SIZE > MODULES_VADDR #error Top of user space clashes with start of module space #endif diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h index 263fed05ea33..bcdb9291ef0c 100644 --- a/arch/arm/include/asm/mmu_context.h +++ b/arch/arm/include/asm/mmu_context.h @@ -62,8 +62,10 @@ static inline void check_context(struct mm_struct *mm) static inline void check_context(struct mm_struct *mm) { +#ifdef CONFIG_MMU if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq)) __check_kvm_seq(mm); +#endif } #define init_new_context(tsk,mm) 0 diff --git a/arch/arm/include/asm/page-nommu.h b/arch/arm/include/asm/page-nommu.h index 3574c0deb37f..d1b162a18dcb 100644 --- a/arch/arm/include/asm/page-nommu.h +++ b/arch/arm/include/asm/page-nommu.h @@ -43,7 +43,4 @@ typedef unsigned long pgprot_t; #define __pmd(x) (x) #define __pgprot(x) (x) -extern unsigned long memory_start; -extern unsigned long memory_end; - #endif diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 67b833c9b6b9..bbecccda76d0 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -82,6 +82,14 @@ #define PSR_ENDSTATE 0 #endif +/* + * These are 'magic' values for PTRACE_PEEKUSR that return info about where a + * process is located in memory. + */ +#define PT_TEXT_ADDR 0x10000 +#define PT_DATA_ADDR 0x10004 +#define PT_TEXT_END_ADDR 0x10008 + #ifndef __ASSEMBLY__ /* diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 321c83e43a1e..f41a6f57cd12 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -102,8 +102,8 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) } #define tlb_remove_page(tlb,page) free_page_and_swap_cache(page) -#define pte_free_tlb(tlb, ptep) pte_free((tlb)->mm, ptep) -#define pmd_free_tlb(tlb, pmdp) pmd_free((tlb)->mm, pmdp) +#define pte_free_tlb(tlb, ptep, addr) pte_free((tlb)->mm, ptep) +#define pmd_free_tlb(tlb, pmdp, addr) pmd_free((tlb)->mm, pmdp) #define tlb_migrate_finish(mm) do { } while (0) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 0da9bc9b3b1d..1d6bd40a4322 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -17,6 +17,7 @@ #include <asm/memory.h> #include <asm/domain.h> #include <asm/system.h> +#include <asm/unified.h> #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -365,8 +366,10 @@ do { \ #define __put_user_asm_dword(x,__pu_addr,err) \ __asm__ __volatile__( \ - "1: strt " __reg_oper1 ", [%1], #4\n" \ - "2: strt " __reg_oper0 ", [%1]\n" \ + ARM( "1: strt " __reg_oper1 ", [%1], #4\n" ) \ + ARM( "2: strt " __reg_oper0 ", [%1]\n" ) \ + THUMB( "1: strt " __reg_oper1 ", [%1]\n" ) \ + THUMB( "2: strt " __reg_oper0 ", [%1, #4]\n" ) \ "3:\n" \ " .section .fixup,\"ax\"\n" \ " .align 2\n" \ diff --git a/arch/arm/include/asm/unified.h b/arch/arm/include/asm/unified.h new file mode 100644 index 000000000000..073e85b9b961 --- /dev/null +++ b/arch/arm/include/asm/unified.h @@ -0,0 +1,126 @@ +/* + * include/asm-arm/unified.h - Unified Assembler Syntax helper macros + * + * Copyright (C) 2008 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_UNIFIED_H +#define __ASM_UNIFIED_H + +#if defined(__ASSEMBLY__) && defined(CONFIG_ARM_ASM_UNIFIED) + .syntax unified +#endif + +#ifdef CONFIG_THUMB2_KERNEL + +#if __GNUC__ < 4 +#error Thumb-2 kernel requires gcc >= 4 +#endif + +/* The CPSR bit describing the instruction set (Thumb) */ +#define PSR_ISETSTATE PSR_T_BIT + +#define ARM(x...) +#define THUMB(x...) x +#define W(instr) instr.w +#define BSYM(sym) sym + 1 + +#else /* !CONFIG_THUMB2_KERNEL */ + +/* The CPSR bit describing the instruction set (ARM) */ +#define PSR_ISETSTATE 0 + +#define ARM(x...) x +#define THUMB(x...) +#define W(instr) instr +#define BSYM(sym) sym + +#endif /* CONFIG_THUMB2_KERNEL */ + +#ifndef CONFIG_ARM_ASM_UNIFIED + +/* + * If the unified assembly syntax isn't used (in ARM mode), these + * macros expand to an empty string + */ +#ifdef __ASSEMBLY__ + .macro it, cond + .endm + .macro itt, cond + .endm + .macro ite, cond + .endm + .macro ittt, cond + .endm + .macro itte, cond + .endm + .macro itet, cond + .endm + .macro itee, cond + .endm + .macro itttt, cond + .endm + .macro ittte, cond + .endm + .macro ittet, cond + .endm + .macro ittee, cond + .endm + .macro itett, cond + .endm + .macro itete, cond + .endm + .macro iteet, cond + .endm + .macro iteee, cond + .endm +#else /* !__ASSEMBLY__ */ +__asm__( +" .macro it, cond\n" +" .endm\n" +" .macro itt, cond\n" +" .endm\n" +" .macro ite, cond\n" +" .endm\n" +" .macro ittt, cond\n" +" .endm\n" +" .macro itte, cond\n" +" .endm\n" +" .macro itet, cond\n" +" .endm\n" +" .macro itee, cond\n" +" .endm\n" +" .macro itttt, cond\n" +" .endm\n" +" .macro ittte, cond\n" +" .endm\n" +" .macro ittet, cond\n" +" .endm\n" +" .macro ittee, cond\n" +" .endm\n" +" .macro itett, cond\n" +" .endm\n" +" .macro itete, cond\n" +" .endm\n" +" .macro iteet, cond\n" +" .endm\n" +" .macro iteee, cond\n" +" .endm\n"); +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_ARM_ASM_UNIFIED */ + +#endif /* !__ASM_UNIFIED_H */ diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 531e1860e546..0e627705f746 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -186,4 +186,5 @@ EXPORT_SYMBOL(_find_next_bit_be); #ifdef CONFIG_FUNCTION_TRACER EXPORT_SYMBOL(mcount); +EXPORT_SYMBOL(__gnu_mcount_nc); #endif diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index fc8af43c5000..3d727a8a23bc 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -34,7 +34,7 @@ @ @ routine called with r0 = irq number, r1 = struct pt_regs * @ - adrne lr, 1b + adrne lr, BSYM(1b) bne asm_do_IRQ #ifdef CONFIG_SMP @@ -46,13 +46,13 @@ */ test_for_ipi r0, r6, r5, lr movne r0, sp - adrne lr, 1b + adrne lr, BSYM(1b) bne do_IPI #ifdef CONFIG_LOCAL_TIMERS test_for_ltirq r0, r6, r5, lr movne r0, sp - adrne lr, 1b + adrne lr, BSYM(1b) bne do_local_timer #endif #endif @@ -70,7 +70,10 @@ */ .macro inv_entry, reason sub sp, sp, #S_FRAME_SIZE - stmib sp, {r1 - lr} + ARM( stmib sp, {r1 - lr} ) + THUMB( stmia sp, {r0 - r12} ) + THUMB( str sp, [sp, #S_SP] ) + THUMB( str lr, [sp, #S_LR] ) mov r1, #\reason .endm @@ -126,17 +129,24 @@ ENDPROC(__und_invalid) .macro svc_entry, stack_hole=0 UNWIND(.fnstart ) UNWIND(.save {r0 - pc} ) - sub sp, sp, #(S_FRAME_SIZE + \stack_hole) + sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) +#ifdef CONFIG_THUMB2_KERNEL + SPFIX( str r0, [sp] ) @ temporarily saved + SPFIX( mov r0, sp ) + SPFIX( tst r0, #4 ) @ test original stack alignment + SPFIX( ldr r0, [sp] ) @ restored +#else SPFIX( tst sp, #4 ) - SPFIX( bicne sp, sp, #4 ) - stmib sp, {r1 - r12} +#endif + SPFIX( subeq sp, sp, #4 ) + stmia sp, {r1 - r12} ldmia r0, {r1 - r3} - add r5, sp, #S_SP @ here for interlock avoidance + add r5, sp, #S_SP - 4 @ here for interlock avoidance mov r4, #-1 @ "" "" "" "" - add r0, sp, #(S_FRAME_SIZE + \stack_hole) - SPFIX( addne r0, r0, #4 ) - str r1, [sp] @ save the "real" r0 copied + add r0, sp, #(S_FRAME_SIZE + \stack_hole - 4) + SPFIX( addeq r0, r0, #4 ) + str r1, [sp, #-4]! @ save the "real" r0 copied @ from the exception stack mov r1, lr @@ -151,6 +161,8 @@ ENDPROC(__und_invalid) @ r4 - orig_r0 (see pt_regs definition in ptrace.h) @ stmia r5, {r0 - r4} + + asm_trace_hardirqs_off .endm .align 5 @@ -196,9 +208,8 @@ __dabt_svc: @ @ restore SPSR and restart the instruction @ - ldr r0, [sp, #S_PSR] - msr spsr_cxsf, r0 - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + ldr r2, [sp, #S_PSR] + svc_exit r2 @ return from exception UNWIND(.fnend ) ENDPROC(__dabt_svc) @@ -206,9 +217,6 @@ ENDPROC(__dabt_svc) __irq_svc: svc_entry -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif #ifdef CONFIG_PREEMPT get_thread_info tsk ldr r8, [tsk, #TI_PREEMPT] @ get preempt count @@ -225,13 +233,12 @@ __irq_svc: tst r0, #_TIF_NEED_RESCHED blne svc_preempt #endif - ldr r0, [sp, #S_PSR] @ irqs are already disabled - msr spsr_cxsf, r0 + ldr r4, [sp, #S_PSR] @ irqs are already disabled #ifdef CONFIG_TRACE_IRQFLAGS - tst r0, #PSR_I_BIT + tst r4, #PSR_I_BIT bleq trace_hardirqs_on #endif - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + svc_exit r4 @ return from exception UNWIND(.fnend ) ENDPROC(__irq_svc) @@ -266,7 +273,7 @@ __und_svc: @ r0 - instruction @ ldr r0, [r2, #-4] - adr r9, 1f + adr r9, BSYM(1f) bl call_fpe mov r0, sp @ struct pt_regs *regs @@ -280,9 +287,8 @@ __und_svc: @ @ restore SPSR and restart the instruction @ - ldr lr, [sp, #S_PSR] @ Get SVC cpsr - msr spsr_cxsf, lr - ldmia sp, {r0 - pc}^ @ Restore SVC registers + ldr r2, [sp, #S_PSR] @ Get SVC cpsr + svc_exit r2 @ return from exception UNWIND(.fnend ) ENDPROC(__und_svc) @@ -323,9 +329,8 @@ __pabt_svc: @ @ restore SPSR and restart the instruction @ - ldr r0, [sp, #S_PSR] - msr spsr_cxsf, r0 - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + ldr r2, [sp, #S_PSR] + svc_exit r2 @ return from exception UNWIND(.fnend ) ENDPROC(__pabt_svc) @@ -353,7 +358,8 @@ ENDPROC(__pabt_svc) UNWIND(.fnstart ) UNWIND(.cantunwind ) @ don't unwind the user space sub sp, sp, #S_FRAME_SIZE - stmib sp, {r1 - r12} + ARM( stmib sp, {r1 - r12} ) + THUMB( stmia sp, {r0 - r12} ) ldmia r0, {r1 - r3} add r0, sp, #S_PC @ here for interlock avoidance @@ -372,7 +378,8 @@ ENDPROC(__pabt_svc) @ Also, separately save sp_usr and lr_usr @ stmia r0, {r2 - r4} - stmdb r0, {sp, lr}^ + ARM( stmdb r0, {sp, lr}^ ) + THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) @ @ Enable the alignment trap while in kernel mode @@ -383,6 +390,8 @@ ENDPROC(__pabt_svc) @ Clear FP to mark the first stack frame @ zero_fp + + asm_trace_hardirqs_off .endm .macro kuser_cmpxchg_check @@ -427,7 +436,7 @@ __dabt_usr: @ enable_irq mov r2, sp - adr lr, ret_from_exception + adr lr, BSYM(ret_from_exception) b do_DataAbort UNWIND(.fnend ) ENDPROC(__dabt_usr) @@ -437,9 +446,6 @@ __irq_usr: usr_entry kuser_cmpxchg_check -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif get_thread_info tsk #ifdef CONFIG_PREEMPT ldr r8, [tsk, #TI_PREEMPT] @ get preempt count @@ -452,7 +458,9 @@ __irq_usr: ldr r0, [tsk, #TI_PREEMPT] str r8, [tsk, #TI_PREEMPT] teq r0, r7 - strne r0, [r0, -r0] + ARM( strne r0, [r0, -r0] ) + THUMB( movne r0, #0 ) + THUMB( strne r0, [r0] ) #endif #ifdef CONFIG_TRACE_IRQFLAGS bl trace_hardirqs_on @@ -476,9 +484,10 @@ __und_usr: @ @ r0 - instruction @ - adr r9, ret_from_exception - adr lr, __und_usr_unknown + adr r9, BSYM(ret_from_exception) + adr lr, BSYM(__und_usr_unknown) tst r3, #PSR_T_BIT @ Thumb mode? + itet eq @ explicit IT needed for the 1f label subeq r4, r2, #4 @ ARM instr at LR - 4 subne r4, r2, #2 @ Thumb instr at LR - 2 1: ldreqt r0, [r4] @@ -488,7 +497,10 @@ __und_usr: beq call_fpe @ Thumb instruction #if __LINUX_ARM_ARCH__ >= 7 -2: ldrht r5, [r4], #2 +2: + ARM( ldrht r5, [r4], #2 ) + THUMB( ldrht r5, [r4] ) + THUMB( add r4, r4, #2 ) and r0, r5, #0xf800 @ mask bits 111x x... .... .... cmp r0, #0xe800 @ 32bit instruction if xx != 0 blo __und_usr_unknown @@ -577,9 +589,11 @@ call_fpe: moveq pc, lr get_thread_info r10 @ get current thread and r8, r0, #0x00000f00 @ mask out CP number + THUMB( lsr r8, r8, #8 ) mov r7, #1 add r6, r10, #TI_USED_CP - strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] + ARM( strb r7, [r6, r8, lsr #8] ) @ set appropriate used_cp[] + THUMB( strb r7, [r6, r8] ) @ set appropriate used_cp[] #ifdef CONFIG_IWMMXT @ Test if we need to give access to iWMMXt coprocessors ldr r5, [r10, #TI_FLAGS] @@ -587,36 +601,38 @@ call_fpe: movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1) bcs iwmmxt_task_enable #endif - add pc, pc, r8, lsr #6 - mov r0, r0 - - mov pc, lr @ CP#0 - b do_fpe @ CP#1 (FPE) - b do_fpe @ CP#2 (FPE) - mov pc, lr @ CP#3 + ARM( add pc, pc, r8, lsr #6 ) + THUMB( lsl r8, r8, #2 ) + THUMB( add pc, r8 ) + nop + + W(mov) pc, lr @ CP#0 + W(b) do_fpe @ CP#1 (FPE) + W(b) do_fpe @ CP#2 (FPE) + W(mov) pc, lr @ CP#3 #ifdef CONFIG_CRUNCH b crunch_task_enable @ CP#4 (MaverickCrunch) b crunch_task_enable @ CP#5 (MaverickCrunch) b crunch_task_enable @ CP#6 (MaverickCrunch) #else - mov pc, lr @ CP#4 - mov pc, lr @ CP#5 - mov pc, lr @ CP#6 + W(mov) pc, lr @ CP#4 + W(mov) pc, lr @ CP#5 + W(mov) pc, lr @ CP#6 #endif - mov pc, lr @ CP#7 - mov pc, lr @ CP#8 - mov pc, lr @ CP#9 + W(mov) pc, lr @ CP#7 + W(mov) pc, lr @ CP#8 + W(mov) pc, lr @ CP#9 #ifdef CONFIG_VFP - b do_vfp @ CP#10 (VFP) - b do_vfp @ CP#11 (VFP) + W(b) do_vfp @ CP#10 (VFP) + W(b) do_vfp @ CP#11 (VFP) #else - mov pc, lr @ CP#10 (VFP) - mov pc, lr @ CP#11 (VFP) + W(mov) pc, lr @ CP#10 (VFP) + W(mov) pc, lr @ CP#11 (VFP) #endif - mov pc, lr @ CP#12 - mov pc, lr @ CP#13 - mov pc, lr @ CP#14 (Debug) - mov pc, lr @ CP#15 (Control) + W(mov) pc, lr @ CP#12 + W(mov) pc, lr @ CP#13 + W(mov) pc, lr @ CP#14 (Debug) + W(mov) pc, lr @ CP#15 (Control) #ifdef CONFIG_NEON .align 6 @@ -667,7 +683,7 @@ no_fp: mov pc, lr __und_usr_unknown: enable_irq mov r0, sp - adr lr, ret_from_exception + adr lr, BSYM(ret_from_exception) b do_undefinstr ENDPROC(__und_usr_unknown) @@ -711,7 +727,10 @@ ENTRY(__switch_to) UNWIND(.cantunwind ) add ip, r1, #TI_CPU_SAVE ldr r3, [r2, #TI_TP_VALUE] - stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack + ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack + THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack + THUMB( str sp, [ip], #4 ) + THUMB( str lr, [ip], #4 ) #ifdef CONFIG_MMU ldr r6, [r2, #TI_CPU_DOMAIN] #endif @@ -736,8 +755,12 @@ ENTRY(__switch_to) ldr r0, =thread_notify_head mov r1, #THREAD_NOTIFY_SWITCH bl atomic_notifier_call_chain + THUMB( mov ip, r4 ) mov r0, r5 - ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously + ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously + THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously + THUMB( ldr sp, [ip], #4 ) + THUMB( ldr pc, [ip] ) UNWIND(.fnend ) ENDPROC(__switch_to) @@ -772,6 +795,7 @@ ENDPROC(__switch_to) * if your compiled code is not going to use the new instructions for other * purpose. */ + THUMB( .arm ) .macro usr_ret, reg #ifdef CONFIG_ARM_THUMB @@ -1020,6 +1044,7 @@ __kuser_helper_version: @ 0xffff0ffc .globl __kuser_helper_end __kuser_helper_end: + THUMB( .thumb ) /* * Vector stubs. @@ -1054,17 +1079,23 @@ vector_\name: @ Prepare for SVC32 mode. IRQs remain disabled. @ mrs r0, cpsr - eor r0, r0, #(\mode ^ SVC_MODE) + eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) msr spsr_cxsf, r0 @ @ the branch table must immediately follow this code @ and lr, lr, #0x0f + THUMB( adr r0, 1f ) + THUMB( ldr lr, [r0, lr, lsl #2] ) mov r0, sp - ldr lr, [pc, lr, lsl #2] + ARM( ldr lr, [pc, lr, lsl #2] ) movs pc, lr @ branch to handler in SVC mode ENDPROC(vector_\name) + + .align 2 + @ handler addresses follow this label +1: .endm .globl __stubs_start @@ -1202,14 +1233,16 @@ __stubs_end: .globl __vectors_start __vectors_start: - swi SYS_ERROR0 - b vector_und + stubs_offset - ldr pc, .LCvswi + stubs_offset - b vector_pabt + stubs_offset - b vector_dabt + stubs_offset - b vector_addrexcptn + stubs_offset - b vector_irq + stubs_offset - b vector_fiq + stubs_offset + ARM( swi SYS_ERROR0 ) + THUMB( svc #0 ) + THUMB( nop ) + W(b) vector_und + stubs_offset + W(ldr) pc, .LCvswi + stubs_offset + W(b) vector_pabt + stubs_offset + W(b) vector_dabt + stubs_offset + W(b) vector_addrexcptn + stubs_offset + W(b) vector_irq + stubs_offset + W(b) vector_fiq + stubs_offset .globl __vectors_end __vectors_end: diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index bfa7f0af7ede..3657c5328a5b 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -33,14 +33,7 @@ ret_fast_syscall: /* perform architecture specific actions before user return */ arch_ret_to_user r1, lr - @ fast_restore_user_regs - ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr - ldr lr, [sp, #S_OFF + S_PC]! @ get pc - msr spsr_cxsf, r1 @ save in spsr_svc - ldmdb sp, {r1 - lr}^ @ get calling r1 - lr - mov r0, r0 - add sp, sp, #S_FRAME_SIZE - S_PC - movs pc, lr @ return & move spsr_svc into cpsr + restore_user_regs fast = 1, offset = S_OFF UNWIND(.fnend ) /* @@ -73,14 +66,7 @@ no_work_pending: /* perform architecture specific actions before user return */ arch_ret_to_user r1, lr - @ slow_restore_user_regs - ldr r1, [sp, #S_PSR] @ get calling cpsr - ldr lr, [sp, #S_PC]! @ get pc - msr spsr_cxsf, r1 @ save in spsr_svc - ldmdb sp, {r0 - lr}^ @ get calling r0 - lr - mov r0, r0 - add sp, sp, #S_FRAME_SIZE - S_PC - movs pc, lr @ return & move spsr_svc into cpsr + restore_user_regs fast = 0, offset = 0 ENDPROC(ret_to_user) /* @@ -132,6 +118,25 @@ ftrace_call: #else +ENTRY(__gnu_mcount_nc) + stmdb sp!, {r0-r3, lr} + ldr r0, =ftrace_trace_function + ldr r2, [r0] + adr r0, ftrace_stub + cmp r0, r2 + bne gnu_trace + ldmia sp!, {r0-r3, ip, lr} + bx ip + +gnu_trace: + ldr r1, [sp, #20] @ lr of instrumented routine + mov r0, lr + sub r0, r0, #MCOUNT_INSN_SIZE + mov lr, pc + mov pc, r2 + ldmia sp!, {r0-r3, ip, lr} + bx ip + ENTRY(mcount) stmdb sp!, {r0-r3, lr} ldr r0, =ftrace_trace_function @@ -182,8 +187,10 @@ ftrace_stub: ENTRY(vector_swi) sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12} @ Calling r0 - r12 - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ @ Calling sp, lr + ARM( add r8, sp, #S_PC ) + ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr + THUMB( mov r8, sp ) + THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr mrs r8, spsr @ called from non-FIQ mode, so ok. str lr, [sp, #S_PC] @ Save calling PC str r8, [sp, #S_PSR] @ Save CPSR @@ -272,7 +279,7 @@ ENTRY(vector_swi) bne __sys_trace cmp scno, #NR_syscalls @ check upper syscall limit - adr lr, ret_fast_syscall @ return address + adr lr, BSYM(ret_fast_syscall) @ return address ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine add r1, sp, #S_OFF @@ -293,7 +300,7 @@ __sys_trace: mov r0, #0 @ trace entry [IP = 0] bl syscall_trace - adr lr, __sys_trace_return @ return address + adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) add r1, sp, #S_R0 + S_OFF @ pointer to regs cmp scno, #NR_syscalls @ check upper syscall limit diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S index 87ab4e157997..a4eaf4f920c5 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -36,11 +36,6 @@ #endif .endm - .macro get_thread_info, rd - mov \rd, sp, lsr #13 - mov \rd, \rd, lsl #13 - .endm - .macro alignment_trap, rtemp #ifdef CONFIG_ALIGNMENT_TRAP ldr \rtemp, .LCcralign @@ -49,6 +44,93 @@ #endif .endm + @ + @ Store/load the USER SP and LR registers by switching to the SYS + @ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not + @ available. Should only be called from SVC mode + @ + .macro store_user_sp_lr, rd, rtemp, offset = 0 + mrs \rtemp, cpsr + eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) + msr cpsr_c, \rtemp @ switch to the SYS mode + + str sp, [\rd, #\offset] @ save sp_usr + str lr, [\rd, #\offset + 4] @ save lr_usr + + eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) + msr cpsr_c, \rtemp @ switch back to the SVC mode + .endm + + .macro load_user_sp_lr, rd, rtemp, offset = 0 + mrs \rtemp, cpsr + eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) + msr cpsr_c, \rtemp @ switch to the SYS mode + + ldr sp, [\rd, #\offset] @ load sp_usr + ldr lr, [\rd, #\offset + 4] @ load lr_usr + + eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) + msr cpsr_c, \rtemp @ switch back to the SVC mode + .endm + +#ifndef CONFIG_THUMB2_KERNEL + .macro svc_exit, rpsr + msr spsr_cxsf, \rpsr + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + .endm + + .macro restore_user_regs, fast = 0, offset = 0 + ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr + ldr lr, [sp, #\offset + S_PC]! @ get pc + msr spsr_cxsf, r1 @ save in spsr_svc + .if \fast + ldmdb sp, {r1 - lr}^ @ get calling r1 - lr + .else + ldmdb sp, {r0 - lr}^ @ get calling r0 - lr + .endif + add sp, sp, #S_FRAME_SIZE - S_PC + movs pc, lr @ return & move spsr_svc into cpsr + .endm + + .macro get_thread_info, rd + mov \rd, sp, lsr #13 + mov \rd, \rd, lsl #13 + .endm +#else /* CONFIG_THUMB2_KERNEL */ + .macro svc_exit, rpsr + ldr r0, [sp, #S_SP] @ top of the stack + ldr r1, [sp, #S_PC] @ return address + tst r0, #4 @ orig stack 8-byte aligned? + stmdb r0, {r1, \rpsr} @ rfe context + ldmia sp, {r0 - r12} + ldr lr, [sp, #S_LR] + addeq sp, sp, #S_FRAME_SIZE - 8 @ aligned + addne sp, sp, #S_FRAME_SIZE - 4 @ not aligned + rfeia sp! + .endm + + .macro restore_user_regs, fast = 0, offset = 0 + mov r2, sp + load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr + ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr + ldr lr, [sp, #\offset + S_PC] @ get pc + add sp, sp, #\offset + S_SP + msr spsr_cxsf, r1 @ save in spsr_svc + .if \fast + ldmdb sp, {r1 - r12} @ get calling r1 - r12 + .else + ldmdb sp, {r0 - r12} @ get calling r0 - r12 + .endif + add sp, sp, #S_FRAME_SIZE - S_SP + movs pc, lr @ return & move spsr_svc into cpsr + .endm + + .macro get_thread_info, rd + mov \rd, sp + lsr \rd, \rd, #13 + mov \rd, \rd, lsl #13 + .endm +#endif /* !CONFIG_THUMB2_KERNEL */ /* * These are the registers used in the syscall handler, and allow us to diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 991952c644d1..93ad576b2d74 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -14,6 +14,7 @@ #define ATAG_CORE 0x54410001 #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) + .align 2 .type __switch_data, %object __switch_data: .long __mmap_switched @@ -51,7 +52,9 @@ __mmap_switched: strcc fp, [r6],#4 bcc 1b - ldmia r3, {r4, r5, r6, r7, sp} + ARM( ldmia r3, {r4, r5, r6, r7, sp}) + THUMB( ldmia r3, {r4, r5, r6, r7} ) + THUMB( ldr sp, [r3, #16] ) str r9, [r4] @ Save processor ID str r1, [r5] @ Save machine type str r2, [r6] @ Save atags pointer @@ -155,7 +158,8 @@ ENDPROC(__error) */ __lookup_processor_type: adr r3, 3f - ldmda r3, {r5 - r7} + ldmia r3, {r5 - r7} + add r3, r3, #8 sub r3, r3, r7 @ get offset between virt&phys add r5, r5, r3 @ convert virt addresses to add r6, r6, r3 @ physical address space @@ -185,9 +189,10 @@ ENDPROC(lookup_processor_type) * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for * more information about the __proc_info and __arch_info structures. */ - .long __proc_info_begin + .align 2 +3: .long __proc_info_begin .long __proc_info_end -3: .long . +4: .long . .long __arch_info_begin .long __arch_info_end @@ -203,7 +208,7 @@ ENDPROC(lookup_processor_type) * r5 = mach_info pointer in physical address space */ __lookup_machine_type: - adr r3, 3b + adr r3, 4b ldmia r3, {r4, r5, r6} sub r3, r3, r4 @ get offset between virt&phys add r5, r5, r3 @ convert virt addresses to diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index cc87e1765ed2..e5dfc2895e24 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -34,7 +34,7 @@ */ .section ".text.head", "ax" ENTRY(stext) - msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode @ and irqs disabled #ifndef CONFIG_CPU_CP15 ldr r9, =CONFIG_PROCESSOR_ID @@ -50,8 +50,10 @@ ENTRY(stext) ldr r13, __switch_data @ address to jump to after @ the initialization is done - adr lr, __after_proc_init @ return (PIC) address - add pc, r10, #PROCINFO_INITFUNC + adr lr, BSYM(__after_proc_init) @ return (PIC) address + ARM( add pc, r10, #PROCINFO_INITFUNC ) + THUMB( add r12, r10, #PROCINFO_INITFUNC ) + THUMB( mov pc, r12 ) ENDPROC(stext) /* @@ -59,7 +61,10 @@ ENDPROC(stext) */ __after_proc_init: #ifdef CONFIG_CPU_CP15 - mrc p15, 0, r0, c1, c0, 0 @ read control reg + /* + * CP15 system control register value returned in r0 from + * the CPU init function. + */ #ifdef CONFIG_ALIGNMENT_TRAP orr r0, r0, #CR_A #else @@ -82,7 +87,8 @@ __after_proc_init: mcr p15, 0, r0, c1, c0, 0 @ write control reg #endif /* CONFIG_CPU_CP15 */ - mov pc, r13 @ clear the BSS and jump + mov r3, r13 + mov pc, r3 @ clear the BSS and jump @ to start_kernel ENDPROC(__after_proc_init) .ltorg diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 21e17dc94cb5..38ccbe1d3b2c 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -76,7 +76,7 @@ */ .section ".text.head", "ax" ENTRY(stext) - msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode @ and irqs disabled mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type @ r5=procinfo r9=cpuid @@ -97,8 +97,10 @@ ENTRY(stext) */ ldr r13, __switch_data @ address to jump to after @ mmu has been enabled - adr lr, __enable_mmu @ return (PIC) address - add pc, r10, #PROCINFO_INITFUNC + adr lr, BSYM(__enable_mmu) @ return (PIC) address + ARM( add pc, r10, #PROCINFO_INITFUNC ) + THUMB( add r12, r10, #PROCINFO_INITFUNC ) + THUMB( mov pc, r12 ) ENDPROC(stext) #if defined(CONFIG_SMP) @@ -110,7 +112,7 @@ ENTRY(secondary_startup) * the processor type - there is no need to check the machine type * as it has already been validated by the primary processor. */ - msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE + setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type movs r10, r5 @ invalid processor? @@ -121,12 +123,15 @@ ENTRY(secondary_startup) * Use the page tables supplied from __cpu_up. */ adr r4, __secondary_data - ldmia r4, {r5, r7, r13} @ address to jump to after + ldmia r4, {r5, r7, r12} @ address to jump to after sub r4, r4, r5 @ mmu has been enabled ldr r4, [r7, r4] @ get secondary_data.pgdir - adr lr, __enable_mmu @ return address - add pc, r10, #PROCINFO_INITFUNC @ initialise processor - @ (return control reg) + adr lr, BSYM(__enable_mmu) @ return address + mov r13, r12 @ __secondary_switched address + ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor + @ (return control reg) + THUMB( add r12, r10, #PROCINFO_INITFUNC ) + THUMB( mov pc, r12 ) ENDPROC(secondary_startup) /* @@ -193,8 +198,8 @@ __turn_mmu_on: mcr p15, 0, r0, c1, c0, 0 @ write control reg mrc p15, 0, r3, c0, c0, 0 @ read id reg mov r3, r3 - mov r3, r3 - mov pc, r13 + mov r3, r13 + mov pc, r3 ENDPROC(__turn_mmu_on) @@ -235,7 +240,8 @@ __create_page_tables: * will be removed by paging_init(). We use our current program * counter to determine corresponding section base address. */ - mov r6, pc, lsr #20 @ start of kernel section + mov r6, pc + mov r6, r6, lsr #20 @ start of kernel section orr r3, r7, r6, lsl #20 @ flags + kernel base str r3, [r4, r6, lsl #2] @ identity mapping diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index b7c3490eaa24..c9a8619f3856 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -86,7 +86,7 @@ int show_interrupts(struct seq_file *p, void *v) unlock: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } else if (i == NR_IRQS) { -#ifdef CONFIG_ARCH_ACORN +#ifdef CONFIG_FIQ show_fiq_list(p, v); #endif #ifdef CONFIG_SMP diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index bac03c81489d..f28c5e9c51ea 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -102,6 +102,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned long loc; Elf32_Sym *sym; s32 offset; + u32 upper, lower, sign, j1, j2; offset = ELF32_R_SYM(rel->r_info); if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { @@ -184,6 +185,58 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, (offset & 0x0fff); break; + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + upper = *(u16 *)loc; + lower = *(u16 *)(loc + 2); + + /* + * 25 bit signed address range (Thumb-2 BL and B.W + * instructions): + * S:I1:I2:imm10:imm11:0 + * where: + * S = upper[10] = offset[24] + * I1 = ~(J1 ^ S) = offset[23] + * I2 = ~(J2 ^ S) = offset[22] + * imm10 = upper[9:0] = offset[21:12] + * imm11 = lower[10:0] = offset[11:1] + * J1 = lower[13] + * J2 = lower[11] + */ + sign = (upper >> 10) & 1; + j1 = (lower >> 13) & 1; + j2 = (lower >> 11) & 1; + offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) | + ((~(j2 ^ sign) & 1) << 22) | + ((upper & 0x03ff) << 12) | + ((lower & 0x07ff) << 1); + if (offset & 0x01000000) + offset -= 0x02000000; + offset += sym->st_value - loc; + + /* only Thumb addresses allowed (no interworking) */ + if (!(offset & 1) || + offset <= (s32)0xff000000 || + offset >= (s32)0x01000000) { + printk(KERN_ERR + "%s: relocation out of range, section " + "%d reloc %d sym '%s'\n", module->name, + relindex, i, strtab + sym->st_name); + return -ENOEXEC; + } + + sign = (offset >> 24) & 1; + j1 = sign ^ (~(offset >> 23) & 1); + j2 = sign ^ (~(offset >> 22) & 1); + *(u16 *)loc = (u16)((upper & 0xf800) | (sign << 10) | + ((offset >> 12) & 0x03ff)); + *(u16 *)(loc + 2) = (u16)((lower & 0xd000) | + (j1 << 13) | (j2 << 11) | + ((offset >> 1) & 0x07ff)); + upper = *(u16 *)loc; + lower = *(u16 *)(loc + 2); + break; + default: printk(KERN_ERR "%s: unknown relocation: %u\n", module->name, ELF32_R_TYPE(rel->r_info)); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 39196dff478c..790fbee92ec5 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -388,7 +388,7 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) regs.ARM_r2 = (unsigned long)fn; regs.ARM_r3 = (unsigned long)kernel_thread_exit; regs.ARM_pc = (unsigned long)kernel_thread_helper; - regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE; + regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE; return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 89882a1d0187..a2ea3854cb3c 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -521,7 +521,13 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, return -EIO; tmp = 0; - if (off < sizeof(struct pt_regs)) + if (off == PT_TEXT_ADDR) + tmp = tsk->mm->start_code; + else if (off == PT_DATA_ADDR) + tmp = tsk->mm->start_data; + else if (off == PT_TEXT_END_ADDR) + tmp = tsk->mm->end_code; + else if (off < sizeof(struct pt_regs)) tmp = get_user_reg(tsk, off >> 2); return put_user(tmp, ret); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index bc5e4128f9f3..d4d4f77c91b2 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -25,6 +25,7 @@ #include <linux/smp.h> #include <linux/fs.h> +#include <asm/unified.h> #include <asm/cpu.h> #include <asm/cputype.h> #include <asm/elf.h> @@ -327,25 +328,38 @@ void cpu_init(void) } /* + * Define the placement constraint for the inline asm directive below. + * In Thumb-2, msr with an immediate value is not allowed. + */ +#ifdef CONFIG_THUMB2_KERNEL +#define PLC "r" +#else +#define PLC "I" +#endif + + /* * setup stacks for re-entrant exception handlers */ __asm__ ( "msr cpsr_c, %1\n\t" - "add sp, %0, %2\n\t" + "add r14, %0, %2\n\t" + "mov sp, r14\n\t" "msr cpsr_c, %3\n\t" - "add sp, %0, %4\n\t" + "add r14, %0, %4\n\t" + "mov sp, r14\n\t" "msr cpsr_c, %5\n\t" - "add sp, %0, %6\n\t" + "add r14, %0, %6\n\t" + "mov sp, r14\n\t" "msr cpsr_c, %7" : : "r" (stk), - "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE), + PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE), "I" (offsetof(struct stack, irq[0])), - "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE), + PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE), "I" (offsetof(struct stack, abt[0])), - "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE), + PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE), "I" (offsetof(struct stack, und[0])), - "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE) + PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) : "r14"); } diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index dd56e11f339a..39baf1128bfa 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -62,7 +62,11 @@ struct unwind_ctrl_block { }; enum regs { +#ifdef CONFIG_THUMB2_KERNEL + FP = 7, +#else FP = 11, +#endif SP = 13, LR = 14, PC = 15 diff --git a/arch/arm/lib/ashldi3.S b/arch/arm/lib/ashldi3.S index 1154d924080b..638deb13da1c 100644 --- a/arch/arm/lib/ashldi3.S +++ b/arch/arm/lib/ashldi3.S @@ -43,7 +43,9 @@ ENTRY(__aeabi_llsl) rsb ip, r2, #32 movmi ah, ah, lsl r2 movpl ah, al, lsl r3 - orrmi ah, ah, al, lsr ip + ARM( orrmi ah, ah, al, lsr ip ) + THUMB( lsrmi r3, al, ip ) + THUMB( orrmi ah, ah, r3 ) mov al, al, lsl r2 mov pc, lr diff --git a/arch/arm/lib/ashrdi3.S b/arch/arm/lib/ashrdi3.S index 9f8b35572f8c..015e8aa5a1d1 100644 --- a/arch/arm/lib/ashrdi3.S +++ b/arch/arm/lib/ashrdi3.S @@ -43,7 +43,9 @@ ENTRY(__aeabi_lasr) rsb ip, r2, #32 movmi al, al, lsr r2 movpl al, ah, asr r3 - orrmi al, al, ah, lsl ip + ARM( orrmi al, al, ah, lsl ip ) + THUMB( lslmi r3, ah, ip ) + THUMB( orrmi al, al, r3 ) mov ah, ah, asr r2 mov pc, lr diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S index b0951d0e8b2c..aaf7220d9e30 100644 --- a/arch/arm/lib/backtrace.S +++ b/arch/arm/lib/backtrace.S @@ -38,7 +38,9 @@ ENDPROC(c_backtrace) beq no_frame @ we have no stack frames tst r1, #0x10 @ 26 or 32-bit mode? - moveq mask, #0xfc000003 @ mask for 26-bit + ARM( moveq mask, #0xfc000003 ) + THUMB( moveq mask, #0xfc000000 ) + THUMB( orreq mask, #0x03 ) movne mask, #0 @ mask for 32-bit 1: stmfd sp!, {pc} @ calculate offset of PC stored @@ -126,7 +128,9 @@ ENDPROC(c_backtrace) mov reg, #10 mov r7, #0 1: mov r3, #1 - tst instr, r3, lsl reg + ARM( tst instr, r3, lsl reg ) + THUMB( lsl r3, reg ) + THUMB( tst instr, r3 ) beq 2f add r7, r7, #1 teq r7, #6 diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index c7f2627385e7..d42252918bfb 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -60,8 +60,8 @@ tst r2, r0, lsl r3 \instr r2, r2, r0, lsl r3 \store r2, [r1] - restore_irqs ip moveq r0, #0 + restore_irqs ip mov pc, lr .endm #endif diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S index 844f56785ebc..1279abd8b886 100644 --- a/arch/arm/lib/clear_user.S +++ b/arch/arm/lib/clear_user.S @@ -27,21 +27,20 @@ WEAK(__clear_user) ands ip, r0, #3 beq 1f cmp ip, #2 -USER( strbt r2, [r0], #1) -USER( strlebt r2, [r0], #1) -USER( strltbt r2, [r0], #1) + strusr r2, r0, 1 + strusr r2, r0, 1, le + strusr r2, r0, 1, lt rsb ip, ip, #4 sub r1, r1, ip @ 7 6 5 4 3 2 1 1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7 -USER( strplt r2, [r0], #4) -USER( strplt r2, [r0], #4) + strusr r2, r0, 4, pl, rept=2 bpl 1b adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3 -USER( strplt r2, [r0], #4) + strusr r2, r0, 4, pl 2: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x -USER( strnebt r2, [r0], #1) -USER( strnebt r2, [r0], #1) + strusr r2, r0, 1, ne, rept=2 tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1 + it ne @ explicit IT needed for the label USER( strnebt r2, [r0]) mov r0, #0 ldmfd sp!, {r1, pc} diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 56799a165cc4..e4fe124acedc 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S @@ -33,11 +33,15 @@ * Number of bytes NOT copied. */ +#ifndef CONFIG_THUMB2_KERNEL +#define LDR1W_SHIFT 0 +#else +#define LDR1W_SHIFT 1 +#endif +#define STR1W_SHIFT 0 + .macro ldr1w ptr reg abort -100: ldrt \reg, [\ptr], #4 - .section __ex_table, "a" - .long 100b, \abort - .previous + ldrusr \reg, \ptr, 4, abort=\abort .endm .macro ldr4w ptr reg1 reg2 reg3 reg4 abort @@ -53,14 +57,11 @@ .endm .macro ldr1b ptr reg cond=al abort -100: ldr\cond\()bt \reg, [\ptr], #1 - .section __ex_table, "a" - .long 100b, \abort - .previous + ldrusr \reg, \ptr, 1, \cond, abort=\abort .endm .macro str1w ptr reg abort - str \reg, [\ptr], #4 + W(str) \reg, [\ptr], #4 .endm .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S index 139cce646055..805e3f8fb007 100644 --- a/arch/arm/lib/copy_template.S +++ b/arch/arm/lib/copy_template.S @@ -57,6 +57,13 @@ * * Restore registers with the values previously saved with the * 'preserv' macro. Called upon code termination. + * + * LDR1W_SHIFT + * STR1W_SHIFT + * + * Correction to be applied to the "ip" register when branching into + * the ldr1w or str1w instructions (some of these macros may expand to + * than one 32bit instruction in Thumb-2) */ @@ -99,9 +106,15 @@ 5: ands ip, r2, #28 rsb ip, ip, #32 +#if LDR1W_SHIFT > 0 + lsl ip, ip, #LDR1W_SHIFT +#endif addne pc, pc, ip @ C is always clear here b 7f -6: nop +6: + .rept (1 << LDR1W_SHIFT) + W(nop) + .endr ldr1w r1, r3, abort=20f ldr1w r1, r4, abort=20f ldr1w r1, r5, abort=20f @@ -110,9 +123,16 @@ ldr1w r1, r8, abort=20f ldr1w r1, lr, abort=20f +#if LDR1W_SHIFT < STR1W_SHIFT + lsl ip, ip, #STR1W_SHIFT - LDR1W_SHIFT +#elif LDR1W_SHIFT > STR1W_SHIFT + lsr ip, ip, #LDR1W_SHIFT - STR1W_SHIFT +#endif add pc, pc, ip nop - nop + .rept (1 << STR1W_SHIFT) + W(nop) + .endr str1w r0, r3, abort=20f str1w r0, r4, abort=20f str1w r0, r5, abort=20f diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S index 878820f0a320..1a71e1584442 100644 --- a/arch/arm/lib/copy_to_user.S +++ b/arch/arm/lib/copy_to_user.S @@ -33,8 +33,15 @@ * Number of bytes NOT copied. */ +#define LDR1W_SHIFT 0 +#ifndef CONFIG_THUMB2_KERNEL +#define STR1W_SHIFT 0 +#else +#define STR1W_SHIFT 1 +#endif + .macro ldr1w ptr reg abort - ldr \reg, [\ptr], #4 + W(ldr) \reg, [\ptr], #4 .endm .macro ldr4w ptr reg1 reg2 reg3 reg4 abort @@ -50,10 +57,7 @@ .endm .macro str1w ptr reg abort -100: strt \reg, [\ptr], #4 - .section __ex_table, "a" - .long 100b, \abort - .previous + strusr \reg, \ptr, 4, abort=\abort .endm .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort @@ -68,10 +72,7 @@ .endm .macro str1b ptr reg cond=al abort -100: str\cond\()bt \reg, [\ptr], #1 - .section __ex_table, "a" - .long 100b, \abort - .previous + strusr \reg, \ptr, 1, \cond, abort=\abort .endm .macro enter reg1 reg2 diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S index 14677fb4b0c4..fd0e9dcd9fdc 100644 --- a/arch/arm/lib/csumpartialcopyuser.S +++ b/arch/arm/lib/csumpartialcopyuser.S @@ -26,50 +26,28 @@ .endm .macro load1b, reg1 -9999: ldrbt \reg1, [r0], $1 - .section __ex_table, "a" - .align 3 - .long 9999b, 6001f - .previous + ldrusr \reg1, r0, 1 .endm .macro load2b, reg1, reg2 -9999: ldrbt \reg1, [r0], $1 -9998: ldrbt \reg2, [r0], $1 - .section __ex_table, "a" - .long 9999b, 6001f - .long 9998b, 6001f - .previous + ldrusr \reg1, r0, 1 + ldrusr \reg2, r0, 1 .endm .macro load1l, reg1 -9999: ldrt \reg1, [r0], $4 - .section __ex_table, "a" - .align 3 - .long 9999b, 6001f - .previous + ldrusr \reg1, r0, 4 .endm .macro load2l, reg1, reg2 -9999: ldrt \reg1, [r0], $4 -9998: ldrt \reg2, [r0], $4 - .section __ex_table, "a" - .long 9999b, 6001f - .long 9998b, 6001f - .previous + ldrusr \reg1, r0, 4 + ldrusr \reg2, r0, 4 .endm .macro load4l, reg1, reg2, reg3, reg4 -9999: ldrt \reg1, [r0], $4 -9998: ldrt \reg2, [r0], $4 -9997: ldrt \reg3, [r0], $4 -9996: ldrt \reg4, [r0], $4 - .section __ex_table, "a" - .long 9999b, 6001f - .long 9998b, 6001f - .long 9997b, 6001f - .long 9996b, 6001f - .previous + ldrusr \reg1, r0, 4 + ldrusr \reg2, r0, 4 + ldrusr \reg3, r0, 4 + ldrusr \reg4, r0, 4 .endm /* @@ -92,14 +70,14 @@ */ .section .fixup,"ax" .align 4 -6001: mov r4, #-EFAULT +9001: mov r4, #-EFAULT ldr r5, [fp, #4] @ *err_ptr str r4, [r5] ldmia sp, {r1, r2} @ retrieve dst, len add r2, r2, r1 mov r0, #0 @ zero the buffer -6002: teq r2, r1 +9002: teq r2, r1 strneb r0, [r1], #1 - bne 6002b + bne 9002b load_regs .previous diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S index 1425e789ba86..faa7748142da 100644 --- a/arch/arm/lib/div64.S +++ b/arch/arm/lib/div64.S @@ -177,7 +177,9 @@ ENTRY(__do_div64) mov yh, xh, lsr ip mov yl, xl, lsr ip rsb ip, ip, #32 - orr yl, yl, xh, lsl ip + ARM( orr yl, yl, xh, lsl ip ) + THUMB( lsl xh, xh, ip ) + THUMB( orr yl, yl, xh ) mov xh, xl, lsl ip mov xh, xh, lsr ip mov pc, lr diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S index 8c4defc4f3c4..1e4cbd4e7be9 100644 --- a/arch/arm/lib/findbit.S +++ b/arch/arm/lib/findbit.S @@ -25,7 +25,10 @@ ENTRY(_find_first_zero_bit_le) teq r1, #0 beq 3f mov r2, #0 -1: ldrb r3, [r0, r2, lsr #3] +1: + ARM( ldrb r3, [r0, r2, lsr #3] ) + THUMB( lsr r3, r2, #3 ) + THUMB( ldrb r3, [r0, r3] ) eors r3, r3, #0xff @ invert bits bne .L_found @ any now set - found zero bit add r2, r2, #8 @ next bit pointer @@ -44,7 +47,9 @@ ENTRY(_find_next_zero_bit_le) beq 3b ands ip, r2, #7 beq 1b @ If new byte, goto old routine - ldrb r3, [r0, r2, lsr #3] + ARM( ldrb r3, [r0, r2, lsr #3] ) + THUMB( lsr r3, r2, #3 ) + THUMB( ldrb r3, [r0, r3] ) eor r3, r3, #0xff @ now looking for a 1 bit movs r3, r3, lsr ip @ shift off unused bits bne .L_found @@ -61,7 +66,10 @@ ENTRY(_find_first_bit_le) teq r1, #0 beq 3f mov r2, #0 -1: ldrb r3, [r0, r2, lsr #3] +1: + ARM( ldrb r3, [r0, r2, lsr #3] ) + THUMB( lsr r3, r2, #3 ) + THUMB( ldrb r3, [r0, r3] ) movs r3, r3 bne .L_found @ any now set - found zero bit add r2, r2, #8 @ next bit pointer @@ -80,7 +88,9 @@ ENTRY(_find_next_bit_le) beq 3b ands ip, r2, #7 beq 1b @ If new byte, goto old routine - ldrb r3, [r0, r2, lsr #3] + ARM( ldrb r3, [r0, r2, lsr #3] ) + THUMB( lsr r3, r2, #3 ) + THUMB( ldrb r3, [r0, r3] ) movs r3, r3, lsr ip @ shift off unused bits bne .L_found orr r2, r2, #7 @ if zero, then no bits here @@ -95,7 +105,9 @@ ENTRY(_find_first_zero_bit_be) beq 3f mov r2, #0 1: eor r3, r2, #0x18 @ big endian byte ordering - ldrb r3, [r0, r3, lsr #3] + ARM( ldrb r3, [r0, r3, lsr #3] ) + THUMB( lsr r3, #3 ) + THUMB( ldrb r3, [r0, r3] ) eors r3, r3, #0xff @ invert bits bne .L_found @ any now set - found zero bit add r2, r2, #8 @ next bit pointer @@ -111,7 +123,9 @@ ENTRY(_find_next_zero_bit_be) ands ip, r2, #7 beq 1b @ If new byte, goto old routine eor r3, r2, #0x18 @ big endian byte ordering - ldrb r3, [r0, r3, lsr #3] + ARM( ldrb r3, [r0, r3, lsr #3] ) + THUMB( lsr r3, #3 ) + THUMB( ldrb r3, [r0, r3] ) eor r3, r3, #0xff @ now looking for a 1 bit movs r3, r3, lsr ip @ shift off unused bits bne .L_found @@ -125,7 +139,9 @@ ENTRY(_find_first_bit_be) beq 3f mov r2, #0 1: eor r3, r2, #0x18 @ big endian byte ordering - ldrb r3, [r0, r3, lsr #3] + ARM( ldrb r3, [r0, r3, lsr #3] ) + THUMB( lsr r3, #3 ) + THUMB( ldrb r3, [r0, r3] ) movs r3, r3 bne .L_found @ any now set - found zero bit add r2, r2, #8 @ next bit pointer @@ -141,7 +157,9 @@ ENTRY(_find_next_bit_be) ands ip, r2, #7 beq 1b @ If new byte, goto old routine eor r3, r2, #0x18 @ big endian byte ordering - ldrb r3, [r0, r3, lsr #3] + ARM( ldrb r3, [r0, r3, lsr #3] ) + THUMB( lsr r3, #3 ) + THUMB( ldrb r3, [r0, r3] ) movs r3, r3, lsr ip @ shift off unused bits bne .L_found orr r2, r2, #7 @ if zero, then no bits here diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 6763088b7607..a1814d927122 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -36,8 +36,13 @@ ENTRY(__get_user_1) ENDPROC(__get_user_1) ENTRY(__get_user_2) +#ifdef CONFIG_THUMB2_KERNEL +2: ldrbt r2, [r0] +3: ldrbt r3, [r0, #1] +#else 2: ldrbt r2, [r0], #1 3: ldrbt r3, [r0] +#endif #ifndef __ARMEB__ orr r2, r2, r3, lsl #8 #else diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S index d6585612c86b..ff4f71b579ee 100644 --- a/arch/arm/lib/io-writesw-armv4.S +++ b/arch/arm/lib/io-writesw-armv4.S @@ -75,7 +75,10 @@ ENTRY(__raw_writesw) #endif .Loutsw_noalign: - ldr r3, [r1, -r3]! + ARM( ldr r3, [r1, -r3]! ) + THUMB( rsb r3, r3, #0 ) + THUMB( ldr r3, [r1, r3] ) + THUMB( sub r1, r3 ) subcs r2, r2, #1 bcs 2f subs r2, r2, #2 diff --git a/arch/arm/lib/lshrdi3.S b/arch/arm/lib/lshrdi3.S index 99ea338bf87c..f83d449141f7 100644 --- a/arch/arm/lib/lshrdi3.S +++ b/arch/arm/lib/lshrdi3.S @@ -43,7 +43,9 @@ ENTRY(__aeabi_llsr) rsb ip, r2, #32 movmi al, al, lsr r2 movpl al, ah, lsr r3 - orrmi al, al, ah, lsl ip + ARM( orrmi al, al, ah, lsl ip ) + THUMB( lslmi r3, ah, ip ) + THUMB( orrmi al, al, r3 ) mov ah, ah, lsr r2 mov pc, lr diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index e0d002641d3f..a9b9e2287a09 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S @@ -13,8 +13,11 @@ #include <linux/linkage.h> #include <asm/assembler.h> +#define LDR1W_SHIFT 0 +#define STR1W_SHIFT 0 + .macro ldr1w ptr reg abort - ldr \reg, [\ptr], #4 + W(ldr) \reg, [\ptr], #4 .endm .macro ldr4w ptr reg1 reg2 reg3 reg4 abort @@ -30,7 +33,7 @@ .endm .macro str1w ptr reg abort - str \reg, [\ptr], #4 + W(str) \reg, [\ptr], #4 .endm .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort diff --git a/arch/arm/lib/memmove.S b/arch/arm/lib/memmove.S index 12549187088c..5025c863713d 100644 --- a/arch/arm/lib/memmove.S +++ b/arch/arm/lib/memmove.S @@ -75,24 +75,24 @@ ENTRY(memmove) addne pc, pc, ip @ C is always clear here b 7f 6: nop - ldr r3, [r1, #-4]! - ldr r4, [r1, #-4]! - ldr r5, [r1, #-4]! - ldr r6, [r1, #-4]! - ldr r7, [r1, #-4]! - ldr r8, [r1, #-4]! - ldr lr, [r1, #-4]! + W(ldr) r3, [r1, #-4]! + W(ldr) r4, [r1, #-4]! + W(ldr) r5, [r1, #-4]! + W(ldr) r6, [r1, #-4]! + W(ldr) r7, [r1, #-4]! + W(ldr) r8, [r1, #-4]! + W(ldr) lr, [r1, #-4]! add pc, pc, ip nop nop - str r3, [r0, #-4]! - str r4, [r0, #-4]! - str r5, [r0, #-4]! - str r6, [r0, #-4]! - str r7, [r0, #-4]! - str r8, [r0, #-4]! - str lr, [r0, #-4]! + W(str) r3, [r0, #-4]! + W(str) r4, [r0, #-4]! + W(str) r5, [r0, #-4]! + W(str) r6, [r0, #-4]! + W(str) r7, [r0, #-4]! + W(str) r8, [r0, #-4]! + W(str) lr, [r0, #-4]! CALGN( bcs 2b ) diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 864f3c1c4f18..02fedbf07c0d 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -37,6 +37,15 @@ ENDPROC(__put_user_1) ENTRY(__put_user_2) mov ip, r2, lsr #8 +#ifdef CONFIG_THUMB2_KERNEL +#ifndef __ARMEB__ +2: strbt r2, [r0] +3: strbt ip, [r0, #1] +#else +2: strbt ip, [r0] +3: strbt r2, [r0, #1] +#endif +#else /* !CONFIG_THUMB2_KERNEL */ #ifndef __ARMEB__ 2: strbt r2, [r0], #1 3: strbt ip, [r0] @@ -44,6 +53,7 @@ ENTRY(__put_user_2) 2: strbt ip, [r0], #1 3: strbt r2, [r0] #endif +#endif /* CONFIG_THUMB2_KERNEL */ mov r0, #0 mov pc, lr ENDPROC(__put_user_2) @@ -55,8 +65,13 @@ ENTRY(__put_user_4) ENDPROC(__put_user_4) ENTRY(__put_user_8) +#ifdef CONFIG_THUMB2_KERNEL +5: strt r2, [r0] +6: strt r3, [r0, #4] +#else 5: strt r2, [r0], #4 6: strt r3, [r0] +#endif mov r0, #0 mov pc, lr ENDPROC(__put_user_8) diff --git a/arch/arm/lib/sha1.S b/arch/arm/lib/sha1.S index a16fb208c841..09b548cac1a4 100644 --- a/arch/arm/lib/sha1.S +++ b/arch/arm/lib/sha1.S @@ -187,6 +187,7 @@ ENTRY(sha_transform) ENDPROC(sha_transform) + .align 2 .L_sha_K: .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 @@ -195,6 +196,7 @@ ENDPROC(sha_transform) * void sha_init(__u32 *buf) */ + .align 2 .L_sha_initial_digest: .word 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 diff --git a/arch/arm/lib/strncpy_from_user.S b/arch/arm/lib/strncpy_from_user.S index 330373c26dd9..1c9814f346c6 100644 --- a/arch/arm/lib/strncpy_from_user.S +++ b/arch/arm/lib/strncpy_from_user.S @@ -23,7 +23,7 @@ ENTRY(__strncpy_from_user) mov ip, r1 1: subs r2, r2, #1 -USER( ldrplbt r3, [r1], #1) + ldrusr r3, r1, 1, pl bmi 2f strb r3, [r0], #1 teq r3, #0 diff --git a/arch/arm/lib/strnlen_user.S b/arch/arm/lib/strnlen_user.S index 90bb9d020836..7855b2906659 100644 --- a/arch/arm/lib/strnlen_user.S +++ b/arch/arm/lib/strnlen_user.S @@ -23,7 +23,7 @@ ENTRY(__strnlen_user) mov r2, r0 1: -USER( ldrbt r3, [r0], #1) + ldrusr r3, r0, 1 teq r3, #0 beq 2f subs r1, r1, #1 diff --git a/arch/arm/mach-at91/include/mach/at_hdmac.h b/arch/arm/mach-at91/include/mach/at_hdmac.h new file mode 100644 index 000000000000..187cb58345c0 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at_hdmac.h @@ -0,0 +1,102 @@ +/* + * Header file for the Atmel AHB DMA Controller driver + * + * Copyright (C) 2008 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef AT_HDMAC_H +#define AT_HDMAC_H + +#include <linux/dmaengine.h> + +/** + * struct at_dma_platform_data - Controller configuration parameters + * @nr_channels: Number of channels supported by hardware (max 8) + * @cap_mask: dma_capability flags supported by the platform + */ +struct at_dma_platform_data { + unsigned int nr_channels; + dma_cap_mask_t cap_mask; +}; + +/** + * enum at_dma_slave_width - DMA slave register access width. + * @AT_DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses + * @AT_DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses + * @AT_DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses + */ +enum at_dma_slave_width { + AT_DMA_SLAVE_WIDTH_8BIT = 0, + AT_DMA_SLAVE_WIDTH_16BIT, + AT_DMA_SLAVE_WIDTH_32BIT, +}; + +/** + * struct at_dma_slave - Controller-specific information about a slave + * @dma_dev: required DMA master device + * @tx_reg: physical address of data register used for + * memory-to-peripheral transfers + * @rx_reg: physical address of data register used for + * peripheral-to-memory transfers + * @reg_width: peripheral register width + * @cfg: Platform-specific initializer for the CFG register + * @ctrla: Platform-specific initializer for the CTRLA register + */ +struct at_dma_slave { + struct device *dma_dev; + dma_addr_t tx_reg; + dma_addr_t rx_reg; + enum at_dma_slave_width reg_width; + u32 cfg; + u32 ctrla; +}; + + +/* Platform-configurable bits in CFG */ +#define ATC_SRC_PER(h) (0xFU & (h)) /* Channel src rq associated with periph handshaking ifc h */ +#define ATC_DST_PER(h) ((0xFU & (h)) << 4) /* Channel dst rq associated with periph handshaking ifc h */ +#define ATC_SRC_REP (0x1 << 8) /* Source Replay Mod */ +#define ATC_SRC_H2SEL (0x1 << 9) /* Source Handshaking Mod */ +#define ATC_SRC_H2SEL_SW (0x0 << 9) +#define ATC_SRC_H2SEL_HW (0x1 << 9) +#define ATC_DST_REP (0x1 << 12) /* Destination Replay Mod */ +#define ATC_DST_H2SEL (0x1 << 13) /* Destination Handshaking Mod */ +#define ATC_DST_H2SEL_SW (0x0 << 13) +#define ATC_DST_H2SEL_HW (0x1 << 13) +#define ATC_SOD (0x1 << 16) /* Stop On Done */ +#define ATC_LOCK_IF (0x1 << 20) /* Interface Lock */ +#define ATC_LOCK_B (0x1 << 21) /* AHB Bus Lock */ +#define ATC_LOCK_IF_L (0x1 << 22) /* Master Interface Arbiter Lock */ +#define ATC_LOCK_IF_L_CHUNK (0x0 << 22) +#define ATC_LOCK_IF_L_BUFFER (0x1 << 22) +#define ATC_AHB_PROT_MASK (0x7 << 24) /* AHB Protection */ +#define ATC_FIFOCFG_MASK (0x3 << 28) /* FIFO Request Configuration */ +#define ATC_FIFOCFG_LARGESTBURST (0x0 << 28) +#define ATC_FIFOCFG_HALFFIFO (0x1 << 28) +#define ATC_FIFOCFG_ENOUGHSPACE (0x2 << 28) + +/* Platform-configurable bits in CTRLA */ +#define ATC_SCSIZE_MASK (0x7 << 16) /* Source Chunk Transfer Size */ +#define ATC_SCSIZE_1 (0x0 << 16) +#define ATC_SCSIZE_4 (0x1 << 16) +#define ATC_SCSIZE_8 (0x2 << 16) +#define ATC_SCSIZE_16 (0x3 << 16) +#define ATC_SCSIZE_32 (0x4 << 16) +#define ATC_SCSIZE_64 (0x5 << 16) +#define ATC_SCSIZE_128 (0x6 << 16) +#define ATC_SCSIZE_256 (0x7 << 16) +#define ATC_DCSIZE_MASK (0x7 << 20) /* Destination Chunk Transfer Size */ +#define ATC_DCSIZE_1 (0x0 << 20) +#define ATC_DCSIZE_4 (0x1 << 20) +#define ATC_DCSIZE_8 (0x2 << 20) +#define ATC_DCSIZE_16 (0x3 << 20) +#define ATC_DCSIZE_32 (0x4 << 20) +#define ATC_DCSIZE_64 (0x5 << 20) +#define ATC_DCSIZE_128 (0x6 << 20) +#define ATC_DCSIZE_256 (0x7 << 20) + +#endif /* AT_HDMAC_H */ diff --git a/arch/arm/mach-ep93xx/dma-m2p.c b/arch/arm/mach-ep93xx/dma-m2p.c index a2df5bb7dff0..dbcac9c40a28 100644 --- a/arch/arm/mach-ep93xx/dma-m2p.c +++ b/arch/arm/mach-ep93xx/dma-m2p.c @@ -33,6 +33,7 @@ #include <linux/err.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/io.h> #include <mach/dma.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-integrator/include/mach/hardware.h b/arch/arm/mach-integrator/include/mach/hardware.h index 1251319ef9ae..d795642fad22 100644 --- a/arch/arm/mach-integrator/include/mach/hardware.h +++ b/arch/arm/mach-integrator/include/mach/hardware.h @@ -36,8 +36,12 @@ #define PCIO_BASE PCI_IO_VADDR #define PCIMEM_BASE PCI_MEMORY_VADDR +#ifdef CONFIG_MMU /* macro to get at IO space when running virtually */ #define IO_ADDRESS(x) (((x) >> 4) + IO_BASE) +#else +#define IO_ADDRESS(x) (x) +#endif #define pcibios_assign_all_busses() 1 diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 69956cdae3c2..2a318eba1b07 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -49,14 +49,14 @@ #define INTCP_PA_CLCD_BASE 0xc0000000 -#define INTCP_VA_CIC_BASE 0xf1000040 -#define INTCP_VA_PIC_BASE 0xf1400000 -#define INTCP_VA_SIC_BASE 0xfca00000 +#define INTCP_VA_CIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE) + 0x40 +#define INTCP_VA_PIC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) +#define INTCP_VA_SIC_BASE IO_ADDRESS(0xca000000) #define INTCP_PA_ETH_BASE 0xc8000000 #define INTCP_ETH_SIZE 0x10 -#define INTCP_VA_CTRL_BASE 0xfcb00000 +#define INTCP_VA_CTRL_BASE IO_ADDRESS(0xcb000000) #define INTCP_FLASHPROG 0x04 #define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0) #define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1) @@ -121,12 +121,12 @@ static struct map_desc intcp_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = 0xfca00000, + .virtual = IO_ADDRESS(0xca000000), .pfn = __phys_to_pfn(0xca000000), .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = 0xfcb00000, + .virtual = IO_ADDRESS(0xcb000000), .pfn = __phys_to_pfn(0xcb000000), .length = SZ_4K, .type = MT_DEVICE @@ -394,8 +394,8 @@ static struct platform_device *intcp_devs[] __initdata = { */ static unsigned int mmc_status(struct device *dev) { - unsigned int status = readl(0xfca00004); - writel(8, 0xfcb00008); + unsigned int status = readl(IO_ADDRESS(0xca000000) + 4); + writel(8, IO_ADDRESS(0xcb000000) + 8); return status & 8; } diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index 25100f7acf4c..0aca451b216d 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -38,6 +38,12 @@ config MACH_TS219 Say 'Y' here if you want your kernel to support the QNAP TS-119 and TS-219 Turbo NAS devices. +config MACH_OPENRD_BASE + bool "Marvell OpenRD Base Board" + help + Say 'Y' here if you want your kernel to support the + Marvell OpenRD Base Board. + endmenu endif diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index 9dd680e964d6..80ab0ec90ee1 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o obj-$(CONFIG_MACH_MV88F6281GTW_GE) += mv88f6281gtw_ge-setup.o obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o obj-$(CONFIG_MACH_TS219) += ts219-setup.o +obj-$(CONFIG_MACH_OPENRD_BASE) += openrd_base-setup.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index 0f6919838011..0acb61f3c10b 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -838,7 +838,8 @@ int __init kirkwood_find_tclk(void) u32 dev, rev; kirkwood_pcie_id(&dev, &rev); - if (dev == MV88F6281_DEV_ID && rev == MV88F6281_REV_A0) + if (dev == MV88F6281_DEV_ID && (rev == MV88F6281_REV_A0 || + rev == MV88F6281_REV_A1)) return 200000000; return 166666667; @@ -872,6 +873,8 @@ static char * __init kirkwood_id(void) return "MV88F6281-Z0"; else if (rev == MV88F6281_REV_A0) return "MV88F6281-A0"; + else if (rev == MV88F6281_REV_A1) + return "MV88F6281-A1"; else return "MV88F6281-Rev-Unsupported"; } else if (dev == MV88F6192_DEV_ID) { diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index 07af858814a0..54c132731d2d 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -101,6 +101,7 @@ #define MV88F6281_DEV_ID 0x6281 #define MV88F6281_REV_Z0 0 #define MV88F6281_REV_A0 2 +#define MV88F6281_REV_A1 3 #define MV88F6192_DEV_ID 0x6192 #define MV88F6192_REV_Z0 0 diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h index e021a80c2caf..bc74278ed311 100644 --- a/arch/arm/mach-kirkwood/mpp.h +++ b/arch/arm/mach-kirkwood/mpp.h @@ -289,7 +289,7 @@ #define MPP48_GPIO MPP( 48, 0x0, 1, 1, 0, 0, 0, 1 ) #define MPP48_TSMP12 MPP( 48, 0x1, 1, 1, 0, 0, 0, 1 ) -#define MPP48_TDM_DTX MPP( 48. 0x2, 0, 1, 0, 0, 0, 1 ) +#define MPP48_TDM_DTX MPP( 48, 0x2, 0, 1, 0, 0, 0, 1 ) #define MPP49_GPIO MPP( 49, 0x0, 1, 1, 0, 0, 0, 1 ) #define MPP49_TSMP9 MPP( 49, 0x1, 1, 1, 0, 0, 0, 1 ) diff --git a/arch/arm/mach-kirkwood/openrd_base-setup.c b/arch/arm/mach-kirkwood/openrd_base-setup.c new file mode 100644 index 000000000000..947dfb8cd5b2 --- /dev/null +++ b/arch/arm/mach-kirkwood/openrd_base-setup.c @@ -0,0 +1,84 @@ +/* + * arch/arm/mach-kirkwood/openrd_base-setup.c + * + * Marvell OpenRD Base Board Setup + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/partitions.h> +#include <linux/ata_platform.h> +#include <linux/mv643xx_eth.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <mach/kirkwood.h> +#include <plat/mvsdio.h> +#include "common.h" +#include "mpp.h" + +static struct mtd_partition openrd_base_nand_parts[] = { + { + .name = "u-boot", + .offset = 0, + .size = SZ_1M + }, { + .name = "uImage", + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_4M + }, { + .name = "root", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL + }, +}; + +static struct mv643xx_eth_platform_data openrd_base_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +static struct mv_sata_platform_data openrd_base_sata_data = { + .n_ports = 2, +}; + +static struct mvsdio_platform_data openrd_base_mvsdio_data = { + .gpio_card_detect = 29, /* MPP29 used as SD card detect */ +}; + +static unsigned int openrd_base_mpp_config[] __initdata = { + MPP29_GPIO, + 0 +}; + +static void __init openrd_base_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + kirkwood_mpp_conf(openrd_base_mpp_config); + + kirkwood_uart0_init(); + kirkwood_nand_init(ARRAY_AND_SIZE(openrd_base_nand_parts), 25); + + kirkwood_ehci_init(); + + kirkwood_ge00_init(&openrd_base_ge00_data); + kirkwood_sata_init(&openrd_base_sata_data); + kirkwood_sdio_init(&openrd_base_mvsdio_data); +} + +MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board") + /* Maintainer: Dhaval Vasa <dhaval.vasa@einfochips.com> */ + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = openrd_base_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &kirkwood_timer, +MACHINE_END diff --git a/arch/arm/mach-mx1/clock.c b/arch/arm/mach-mx1/clock.c index 0d0f306851d0..d1b588519ad2 100644 --- a/arch/arm/mach-mx1/clock.c +++ b/arch/arm/mach-mx1/clock.c @@ -18,11 +18,14 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/list.h> #include <linux/math64.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <asm/clkdev.h> + #include <mach/clock.h> #include <mach/hardware.h> #include <mach/common.h> @@ -94,7 +97,6 @@ static unsigned long clk16m_get_rate(struct clk *clk) } static struct clk clk16m = { - .name = "CLK16M", .get_rate = clk16m_get_rate, .enable = _clk_enable, .enable_reg = CCM_CSCR, @@ -111,7 +113,6 @@ static unsigned long clk32_get_rate(struct clk *clk) } static struct clk clk32 = { - .name = "CLK32", .get_rate = clk32_get_rate, }; @@ -121,7 +122,6 @@ static unsigned long clk32_premult_get_rate(struct clk *clk) } static struct clk clk32_premult = { - .name = "CLK32_premultiplier", .parent = &clk32, .get_rate = clk32_premult_get_rate, }; @@ -156,7 +156,6 @@ static int prem_clk_set_parent(struct clk *clk, struct clk *parent) } static struct clk prem_clk = { - .name = "prem_clk", .set_parent = prem_clk_set_parent, }; @@ -167,7 +166,6 @@ static unsigned long system_clk_get_rate(struct clk *clk) } static struct clk system_clk = { - .name = "system_clk", .parent = &prem_clk, .get_rate = system_clk_get_rate, }; @@ -179,7 +177,6 @@ static unsigned long mcu_clk_get_rate(struct clk *clk) } static struct clk mcu_clk = { - .name = "mcu_clk", .parent = &clk32_premult, .get_rate = mcu_clk_get_rate, }; @@ -195,7 +192,6 @@ static unsigned long fclk_get_rate(struct clk *clk) } static struct clk fclk = { - .name = "fclk", .parent = &mcu_clk, .get_rate = fclk_get_rate, }; @@ -238,7 +234,6 @@ static int hclk_set_rate(struct clk *clk, unsigned long rate) } static struct clk hclk = { - .name = "hclk", .parent = &system_clk, .get_rate = hclk_get_rate, .round_rate = hclk_round_rate, @@ -280,7 +275,6 @@ static int clk48m_set_rate(struct clk *clk, unsigned long rate) } static struct clk clk48m = { - .name = "CLK48M", .parent = &system_clk, .get_rate = clk48m_get_rate, .round_rate = clk48m_round_rate, @@ -400,21 +394,18 @@ static int perclk3_set_rate(struct clk *clk, unsigned long rate) static struct clk perclk[] = { { - .name = "perclk", .id = 0, .parent = &system_clk, .get_rate = perclk1_get_rate, .round_rate = perclk1_round_rate, .set_rate = perclk1_set_rate, }, { - .name = "perclk", .id = 1, .parent = &system_clk, .get_rate = perclk2_get_rate, .round_rate = perclk2_round_rate, .set_rate = perclk2_set_rate, }, { - .name = "perclk", .id = 2, .parent = &system_clk, .get_rate = perclk3_get_rate, @@ -457,12 +448,10 @@ static int clko_set_parent(struct clk *clk, struct clk *parent) } static struct clk clko_clk = { - .name = "clko_clk", .set_parent = clko_set_parent, }; static struct clk dma_clk = { - .name = "dma", .parent = &hclk, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, @@ -473,7 +462,6 @@ static struct clk dma_clk = { }; static struct clk csi_clk = { - .name = "csi_clk", .parent = &hclk, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, @@ -484,7 +472,6 @@ static struct clk csi_clk = { }; static struct clk mma_clk = { - .name = "mma_clk", .parent = &hclk, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, @@ -495,7 +482,6 @@ static struct clk mma_clk = { }; static struct clk usbd_clk = { - .name = "usbd_clk", .parent = &clk48m, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, @@ -506,99 +492,85 @@ static struct clk usbd_clk = { }; static struct clk gpt_clk = { - .name = "gpt_clk", .parent = &perclk[0], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk uart_clk = { - .name = "uart", .parent = &perclk[0], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk i2c_clk = { - .name = "i2c_clk", .parent = &hclk, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk spi_clk = { - .name = "spi_clk", .parent = &perclk[1], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk sdhc_clk = { - .name = "sdhc_clk", .parent = &perclk[1], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk lcdc_clk = { - .name = "lcdc_clk", .parent = &perclk[1], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk mshc_clk = { - .name = "mshc_clk", .parent = &hclk, .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk ssi_clk = { - .name = "ssi_clk", .parent = &perclk[2], .round_rate = _clk_parent_round_rate, .set_rate = _clk_parent_set_rate, }; static struct clk rtc_clk = { - .name = "rtc_clk", .parent = &clk32, }; -static struct clk *mxc_clks[] = { - &clk16m, - &clk32, - &clk32_premult, - &prem_clk, - &system_clk, - &mcu_clk, - &fclk, - &hclk, - &clk48m, - &perclk[0], - &perclk[1], - &perclk[2], - &clko_clk, - &dma_clk, - &csi_clk, - &mma_clk, - &usbd_clk, - &gpt_clk, - &uart_clk, - &i2c_clk, - &spi_clk, - &sdhc_clk, - &lcdc_clk, - &mshc_clk, - &ssi_clk, - &rtc_clk, +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, +static struct clk_lookup lookups[] __initdata = { + _REGISTER_CLOCK(NULL, "dma", dma_clk) + _REGISTER_CLOCK("mx1-camera.0", NULL, csi_clk) + _REGISTER_CLOCK(NULL, "mma", mma_clk) + _REGISTER_CLOCK("imx_udc.0", NULL, usbd_clk) + _REGISTER_CLOCK(NULL, "gpt", gpt_clk) + _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk) + _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk) + _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk) + _REGISTER_CLOCK("spi_imx.0", NULL, spi_clk) + _REGISTER_CLOCK("imx-mmc.0", NULL, sdhc_clk) + _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) + _REGISTER_CLOCK(NULL, "mshc", mshc_clk) + _REGISTER_CLOCK(NULL, "ssi", ssi_clk) + _REGISTER_CLOCK("mxc_rtc.0", NULL, rtc_clk) }; int __init mx1_clocks_init(unsigned long fref) { - struct clk **clkp; unsigned int reg; + int i; /* disable clocks we are able to */ __raw_writel(0, SCM_GCCR); @@ -620,13 +592,13 @@ int __init mx1_clocks_init(unsigned long fref) reg = (reg & CCM_CSCR_CLKO_MASK) >> CCM_CSCR_CLKO_OFFSET; clko_clk.parent = (struct clk *)clko_clocks[reg]; - for (clkp = mxc_clks; clkp < mxc_clks + ARRAY_SIZE(mxc_clks); clkp++) - clk_register(*clkp); + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); clk_enable(&hclk); clk_enable(&fclk); - mxc_timer_init(&gpt_clk); + mxc_timer_init(&gpt_clk, IO_ADDRESS(TIM1_BASE_ADDR), TIM1_INT); return 0; } diff --git a/arch/arm/mach-mx1/devices.c b/arch/arm/mach-mx1/devices.c index 76d1ffb48079..b6be29d1cb08 100644 --- a/arch/arm/mach-mx1/devices.c +++ b/arch/arm/mach-mx1/devices.c @@ -29,12 +29,11 @@ #include "devices.h" static struct resource imx_csi_resources[] = { - [0] = { + { .start = 0x00224000, .end = 0x00224010, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = CSI_INT, .end = CSI_INT, .flags = IORESOURCE_IRQ, @@ -55,12 +54,11 @@ struct platform_device imx_csi_device = { }; static struct resource imx_i2c_resources[] = { - [0] = { + { .start = 0x00217000, .end = 0x00217010, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = I2C_INT, .end = I2C_INT, .flags = IORESOURCE_IRQ, @@ -75,22 +73,19 @@ struct platform_device imx_i2c_device = { }; static struct resource imx_uart1_resources[] = { - [0] = { + { .start = UART1_BASE_ADDR, .end = UART1_BASE_ADDR + 0xD0, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = UART1_MINT_RX, .end = UART1_MINT_RX, .flags = IORESOURCE_IRQ, - }, - [2] = { + }, { .start = UART1_MINT_TX, .end = UART1_MINT_TX, .flags = IORESOURCE_IRQ, - }, - [3] = { + }, { .start = UART1_MINT_RTS, .end = UART1_MINT_RTS, .flags = IORESOURCE_IRQ, @@ -105,22 +100,19 @@ struct platform_device imx_uart1_device = { }; static struct resource imx_uart2_resources[] = { - [0] = { + { .start = UART2_BASE_ADDR, .end = UART2_BASE_ADDR + 0xD0, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = UART2_MINT_RX, .end = UART2_MINT_RX, .flags = IORESOURCE_IRQ, - }, - [2] = { + }, { .start = UART2_MINT_TX, .end = UART2_MINT_TX, .flags = IORESOURCE_IRQ, - }, - [3] = { + }, { .start = UART2_MINT_RTS, .end = UART2_MINT_RTS, .flags = IORESOURCE_IRQ, @@ -135,17 +127,15 @@ struct platform_device imx_uart2_device = { }; static struct resource imx_rtc_resources[] = { - [0] = { + { .start = 0x00204000, .end = 0x00204024, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = RTC_INT, .end = RTC_INT, .flags = IORESOURCE_IRQ, - }, - [2] = { + }, { .start = RTC_SAMINT, .end = RTC_SAMINT, .flags = IORESOURCE_IRQ, @@ -160,12 +150,11 @@ struct platform_device imx_rtc_device = { }; static struct resource imx_wdt_resources[] = { - [0] = { + { .start = 0x00201000, .end = 0x00201008, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = WDT_INT, .end = WDT_INT, .flags = IORESOURCE_IRQ, @@ -180,42 +169,35 @@ struct platform_device imx_wdt_device = { }; static struct resource imx_usb_resources[] = { - [0] = { + { .start = 0x00212000, .end = 0x00212148, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = USBD_INT0, .end = USBD_INT0, .flags = IORESOURCE_IRQ, - }, - [2] = { + }, { .start = USBD_INT1, .end = USBD_INT1, .flags = IORESOURCE_IRQ, - }, - [3] = { + }, { .start = USBD_INT2, .end = USBD_INT2, .flags = IORESOURCE_IRQ, - }, - [4] = { + }, { .start = USBD_INT3, .end = USBD_INT3, .flags = IORESOURCE_IRQ, - }, - [5] = { + }, { .start = USBD_INT4, .end = USBD_INT4, .flags = IORESOURCE_IRQ, - }, - [6] = { + }, { .start = USBD_INT5, .end = USBD_INT5, .flags = IORESOURCE_IRQ, - }, - [7] = { + }, { .start = USBD_INT6, .end = USBD_INT6, .flags = IORESOURCE_IRQ, @@ -231,29 +213,26 @@ struct platform_device imx_usb_device = { /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { - [0] = { + { .chip.label = "gpio-0", .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR), .irq = GPIO_INT_PORTA, - .virtual_irq_start = MXC_GPIO_IRQ_START - }, - [1] = { + .virtual_irq_start = MXC_GPIO_IRQ_START, + }, { .chip.label = "gpio-1", .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x100), .irq = GPIO_INT_PORTB, - .virtual_irq_start = MXC_GPIO_IRQ_START + 32 - }, - [2] = { + .virtual_irq_start = MXC_GPIO_IRQ_START + 32, + }, { .chip.label = "gpio-2", .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x200), .irq = GPIO_INT_PORTC, - .virtual_irq_start = MXC_GPIO_IRQ_START + 64 - }, - [3] = { + .virtual_irq_start = MXC_GPIO_IRQ_START + 64, + }, { .chip.label = "gpio-3", .base = (void __iomem *)IO_ADDRESS(GPIO_BASE_ADDR + 0x300), .irq = GPIO_INT_PORTD, - .virtual_irq_start = MXC_GPIO_IRQ_START + 96 + .virtual_irq_start = MXC_GPIO_IRQ_START + 96, } }; diff --git a/arch/arm/mach-mx1/generic.c b/arch/arm/mach-mx1/generic.c index 7622c9b38c97..7f9fc1034c08 100644 --- a/arch/arm/mach-mx1/generic.c +++ b/arch/arm/mach-mx1/generic.c @@ -41,6 +41,13 @@ static struct map_desc imx_io_desc[] __initdata = { void __init mx1_map_io(void) { mxc_set_cpu_type(MXC_CPU_MX1); + mxc_arch_reset_init(IO_ADDRESS(WDT_BASE_ADDR)); iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc)); } + +void __init mx1_init_irq(void) +{ + mxc_init_irq(IO_ADDRESS(AVIC_BASE_ADDR)); +} + diff --git a/arch/arm/mach-mx1/mx1ads.c b/arch/arm/mach-mx1/mx1ads.c index e5b0c0a83c3b..30f04e56fafe 100644 --- a/arch/arm/mach-mx1/mx1ads.c +++ b/arch/arm/mach-mx1/mx1ads.c @@ -104,12 +104,10 @@ static struct imxi2c_platform_data mx1ads_i2c_data = { static struct i2c_board_info mx1ads_i2c_devices[] = { { - I2C_BOARD_INFO("pcf857x", 0x22), - .type = "pcf8575", + I2C_BOARD_INFO("pcf8575", 0x22), .platform_data = &pcf857x_data[0], }, { - I2C_BOARD_INFO("pcf857x", 0x24), - .type = "pcf8575", + I2C_BOARD_INFO("pcf8575", 0x24), .platform_data = &pcf857x_data[1], }, }; @@ -151,7 +149,7 @@ MACHINE_START(MX1ADS, "Freescale MX1ADS") .io_pg_offst = (IMX_IO_BASE >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx1_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx1_init_irq, .timer = &mx1ads_timer, .init_machine = mx1ads_init, MACHINE_END @@ -161,7 +159,7 @@ MACHINE_START(MXLADS, "Freescale MXLADS") .io_pg_offst = (IMX_IO_BASE >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx1_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx1_init_irq, .timer = &mx1ads_timer, .init_machine = mx1ads_init, MACHINE_END diff --git a/arch/arm/mach-mx1/scb9328.c b/arch/arm/mach-mx1/scb9328.c index 20e0b5bcdffc..325d98df6053 100644 --- a/arch/arm/mach-mx1/scb9328.c +++ b/arch/arm/mach-mx1/scb9328.c @@ -68,22 +68,20 @@ static struct dm9000_plat_data dm9000_platdata = { * to gain access to address latch registers and the data path. */ static struct resource dm9000x_resources[] = { - [0] = { + { .name = "address area", .start = IMX_CS5_PHYS, .end = IMX_CS5_PHYS + 1, - .flags = IORESOURCE_MEM /* address access */ - }, - [1] = { + .flags = IORESOURCE_MEM, /* address access */ + }, { .name = "data area", .start = IMX_CS5_PHYS + 4, .end = IMX_CS5_PHYS + 5, - .flags = IORESOURCE_MEM /* data access */ - }, - [2] = { + .flags = IORESOURCE_MEM, /* data access */ + }, { .start = IRQ_GPIOC(3), .end = IRQ_GPIOC(3), - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, }, }; @@ -154,7 +152,7 @@ MACHINE_START(SCB9328, "Synertronixx scb9328") .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc, .boot_params = 0x08000100, .map_io = mx1_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx1_init_irq, .timer = &scb9328_timer, .init_machine = scb9328_init, MACHINE_END diff --git a/arch/arm/mach-mx2/Kconfig b/arch/arm/mach-mx2/Kconfig index c77da586b71d..c8a2eac4d13c 100644 --- a/arch/arm/mach-mx2/Kconfig +++ b/arch/arm/mach-mx2/Kconfig @@ -53,6 +53,34 @@ config MACH_PCM970_BASEBOARD endchoice +config MACH_EUKREA_CPUIMX27 + bool "Eukrea CPUIMX27 module" + depends on MACH_MX27 + help + Include support for Eukrea CPUIMX27 platform. This includes + specific configurations for the module and its peripherals. + +config MACH_EUKREA_CPUIMX27_USESDHC2 + bool "CPUIMX27 integrates SDHC2 module" + depends on MACH_EUKREA_CPUIMX27 + help + This adds support for the internal SDHC2 used on CPUIMX27 used + for wifi or eMMC. + +choice + prompt "Baseboard" + depends on MACH_EUKREA_CPUIMX27 + default MACH_EUKREA_MBIMX27_BASEBOARD + +config MACH_EUKREA_MBIMX27_BASEBOARD + prompt "Eukrea MBIMX27 development board" + bool + help + This adds board specific devices that can be found on Eukrea's + MBIMX27 evaluation board. + +endchoice + config MACH_MX27_3DS bool "MX27PDK platform" depends on MACH_MX27 @@ -67,4 +95,11 @@ config MACH_MX27LITE Include support for MX27 LITEKIT platform. This includes specific configurations for the board and its peripherals. +config MACH_PCA100 + bool "Phytec phyCARD-s (pca100)" + depends on MACH_MX27 + help + Include support for phyCARD-s (aka pca100) platform. This + includes specific configurations for the module and its peripherals. + endif diff --git a/arch/arm/mach-mx2/Makefile b/arch/arm/mach-mx2/Makefile index b9b1cca4e9bc..19560f045632 100644 --- a/arch/arm/mach-mx2/Makefile +++ b/arch/arm/mach-mx2/Makefile @@ -17,4 +17,7 @@ obj-$(CONFIG_MACH_PCM038) += pcm038.o obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o obj-$(CONFIG_MACH_MX27_3DS) += mx27pdk.o obj-$(CONFIG_MACH_MX27LITE) += mx27lite.o +obj-$(CONFIG_MACH_EUKREA_CPUIMX27) += eukrea_cpuimx27.o +obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o +obj-$(CONFIG_MACH_PCA100) += pca100.o diff --git a/arch/arm/mach-mx2/clock_imx21.c b/arch/arm/mach-mx2/clock_imx21.c index 0850fb88ec15..eede79855f4a 100644 --- a/arch/arm/mach-mx2/clock_imx21.c +++ b/arch/arm/mach-mx2/clock_imx21.c @@ -1004,6 +1004,6 @@ int __init mx21_clocks_init(unsigned long lref, unsigned long href) clk_enable(&uart_clk[0]); #endif - mxc_timer_init(&gpt_clk[0]); + mxc_timer_init(&gpt_clk[0], IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT1); return 0; } diff --git a/arch/arm/mach-mx2/clock_imx27.c b/arch/arm/mach-mx2/clock_imx27.c index 2c971442f3f2..4089951acb47 100644 --- a/arch/arm/mach-mx2/clock_imx27.c +++ b/arch/arm/mach-mx2/clock_imx27.c @@ -643,7 +643,14 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "cspi3", cspi3_clk) _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) _REGISTER_CLOCK(NULL, "csi", csi_clk) - _REGISTER_CLOCK(NULL, "usb", usb_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk1) _REGISTER_CLOCK(NULL, "ssi1", ssi1_clk) _REGISTER_CLOCK(NULL, "ssi2", ssi2_clk) _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) @@ -748,7 +755,7 @@ int __init mx27_clocks_init(unsigned long fref) clk_enable(&uart1_clk); #endif - mxc_timer_init(&gpt1_clk); + mxc_timer_init(&gpt1_clk, IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT1); return 0; } diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index a0f1b3674327..50199aff0143 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -40,45 +40,87 @@ #include "devices.h" /* - * Resource definition for the MXC IrDA + * SPI master controller + * + * - i.MX1: 2 channel (slighly different register setting) + * - i.MX21: 2 channel + * - i.MX27: 3 channel */ -static struct resource mxc_irda_resources[] = { - [0] = { - .start = UART3_BASE_ADDR, - .end = UART3_BASE_ADDR + SZ_4K - 1, - .flags = IORESOURCE_MEM, +static struct resource mxc_spi_resources0[] = { + { + .start = CSPI1_BASE_ADDR, + .end = CSPI1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_CSPI1, + .end = MXC_INT_CSPI1, + .flags = IORESOURCE_IRQ, }, - [1] = { - .start = MXC_INT_UART3, - .end = MXC_INT_UART3, - .flags = IORESOURCE_IRQ, +}; + +static struct resource mxc_spi_resources1[] = { + { + .start = CSPI2_BASE_ADDR, + .end = CSPI2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_CSPI2, + .end = MXC_INT_CSPI2, + .flags = IORESOURCE_IRQ, }, }; -/* Platform Data for MXC IrDA */ -struct platform_device mxc_irda_device = { - .name = "mxc_irda", +#ifdef CONFIG_MACH_MX27 +static struct resource mxc_spi_resources2[] = { + { + .start = CSPI3_BASE_ADDR, + .end = CSPI3_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_CSPI3, + .end = MXC_INT_CSPI3, + .flags = IORESOURCE_IRQ, + }, +}; +#endif + +struct platform_device mxc_spi_device0 = { + .name = "spi_imx", .id = 0, - .num_resources = ARRAY_SIZE(mxc_irda_resources), - .resource = mxc_irda_resources, + .num_resources = ARRAY_SIZE(mxc_spi_resources0), + .resource = mxc_spi_resources0, +}; + +struct platform_device mxc_spi_device1 = { + .name = "spi_imx", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_spi_resources1), + .resource = mxc_spi_resources1, +}; + +#ifdef CONFIG_MACH_MX27 +struct platform_device mxc_spi_device2 = { + .name = "spi_imx", + .id = 2, + .num_resources = ARRAY_SIZE(mxc_spi_resources2), + .resource = mxc_spi_resources2, }; +#endif /* * General Purpose Timer - * - i.MX1: 2 timer (slighly different register handling) - * - i.MX21: 3 timer - * - i.MX27: 6 timer + * - i.MX21: 3 timers + * - i.MX27: 6 timers */ /* We use gpt0 as system timer, so do not add a device for this one */ static struct resource timer1_resources[] = { - [0] = { + { .start = GPT2_BASE_ADDR, .end = GPT2_BASE_ADDR + 0x17, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_GPT2, .end = MXC_INT_GPT2, .flags = IORESOURCE_IRQ, @@ -89,16 +131,15 @@ struct platform_device mxc_gpt1 = { .name = "imx_gpt", .id = 1, .num_resources = ARRAY_SIZE(timer1_resources), - .resource = timer1_resources + .resource = timer1_resources, }; static struct resource timer2_resources[] = { - [0] = { + { .start = GPT3_BASE_ADDR, .end = GPT3_BASE_ADDR + 0x17, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_GPT3, .end = MXC_INT_GPT3, .flags = IORESOURCE_IRQ, @@ -109,17 +150,16 @@ struct platform_device mxc_gpt2 = { .name = "imx_gpt", .id = 2, .num_resources = ARRAY_SIZE(timer2_resources), - .resource = timer2_resources + .resource = timer2_resources, }; #ifdef CONFIG_MACH_MX27 static struct resource timer3_resources[] = { - [0] = { + { .start = GPT4_BASE_ADDR, .end = GPT4_BASE_ADDR + 0x17, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_GPT4, .end = MXC_INT_GPT4, .flags = IORESOURCE_IRQ, @@ -130,16 +170,15 @@ struct platform_device mxc_gpt3 = { .name = "imx_gpt", .id = 3, .num_resources = ARRAY_SIZE(timer3_resources), - .resource = timer3_resources + .resource = timer3_resources, }; static struct resource timer4_resources[] = { - [0] = { + { .start = GPT5_BASE_ADDR, .end = GPT5_BASE_ADDR + 0x17, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_GPT5, .end = MXC_INT_GPT5, .flags = IORESOURCE_IRQ, @@ -150,16 +189,15 @@ struct platform_device mxc_gpt4 = { .name = "imx_gpt", .id = 4, .num_resources = ARRAY_SIZE(timer4_resources), - .resource = timer4_resources + .resource = timer4_resources, }; static struct resource timer5_resources[] = { - [0] = { + { .start = GPT6_BASE_ADDR, .end = GPT6_BASE_ADDR + 0x17, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_GPT6, .end = MXC_INT_GPT6, .flags = IORESOURCE_IRQ, @@ -170,7 +208,7 @@ struct platform_device mxc_gpt5 = { .name = "imx_gpt", .id = 5, .num_resources = ARRAY_SIZE(timer5_resources), - .resource = timer5_resources + .resource = timer5_resources, }; #endif @@ -214,11 +252,11 @@ static struct resource mxc_nand_resources[] = { { .start = NFC_BASE_ADDR, .end = NFC_BASE_ADDR + 0xfff, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_MEM, }, { .start = MXC_INT_NANDFC, .end = MXC_INT_NANDFC, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ, }, }; @@ -240,8 +278,7 @@ static struct resource mxc_fb[] = { .start = LCDC_BASE_ADDR, .end = LCDC_BASE_ADDR + 0xFFF, .flags = IORESOURCE_MEM, - }, - { + }, { .start = MXC_INT_LCDC, .end = MXC_INT_LCDC, .flags = IORESOURCE_IRQ, @@ -264,11 +301,11 @@ static struct resource mxc_fec_resources[] = { { .start = FEC_BASE_ADDR, .end = FEC_BASE_ADDR + 0xfff, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_MEM, }, { .start = MXC_INT_FEC, .end = MXC_INT_FEC, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ, }, }; @@ -281,15 +318,14 @@ struct platform_device mxc_fec_device = { #endif static struct resource mxc_i2c_1_resources[] = { - [0] = { + { .start = I2C_BASE_ADDR, .end = I2C_BASE_ADDR + 0x0fff, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_I2C, .end = MXC_INT_I2C, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ, } }; @@ -297,20 +333,19 @@ struct platform_device mxc_i2c_device0 = { .name = "imx-i2c", .id = 0, .num_resources = ARRAY_SIZE(mxc_i2c_1_resources), - .resource = mxc_i2c_1_resources + .resource = mxc_i2c_1_resources, }; #ifdef CONFIG_MACH_MX27 static struct resource mxc_i2c_2_resources[] = { - [0] = { + { .start = I2C2_BASE_ADDR, .end = I2C2_BASE_ADDR + 0x0fff, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_I2C2, .end = MXC_INT_I2C2, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ, } }; @@ -318,17 +353,16 @@ struct platform_device mxc_i2c_device1 = { .name = "imx-i2c", .id = 1, .num_resources = ARRAY_SIZE(mxc_i2c_2_resources), - .resource = mxc_i2c_2_resources + .resource = mxc_i2c_2_resources, }; #endif static struct resource mxc_pwm_resources[] = { - [0] = { + { .start = PWM_BASE_ADDR, .end = PWM_BASE_ADDR + 0x0fff, - .flags = IORESOURCE_MEM - }, - [1] = { + .flags = IORESOURCE_MEM, + }, { .start = MXC_INT_PWM, .end = MXC_INT_PWM, .flags = IORESOURCE_IRQ, @@ -339,28 +373,26 @@ struct platform_device mxc_pwm_device = { .name = "mxc_pwm", .id = 0, .num_resources = ARRAY_SIZE(mxc_pwm_resources), - .resource = mxc_pwm_resources + .resource = mxc_pwm_resources, }; /* * Resource definition for the MXC SDHC */ static struct resource mxc_sdhc1_resources[] = { - [0] = { - .start = SDHC1_BASE_ADDR, - .end = SDHC1_BASE_ADDR + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MXC_INT_SDHC1, - .end = MXC_INT_SDHC1, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = DMA_REQ_SDHC1, - .end = DMA_REQ_SDHC1, - .flags = IORESOURCE_DMA - }, + { + .start = SDHC1_BASE_ADDR, + .end = SDHC1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_SDHC1, + .end = MXC_INT_SDHC1, + .flags = IORESOURCE_IRQ, + }, { + .start = DMA_REQ_SDHC1, + .end = DMA_REQ_SDHC1, + .flags = IORESOURCE_DMA, + }, }; static u64 mxc_sdhc1_dmamask = 0xffffffffUL; @@ -377,21 +409,19 @@ struct platform_device mxc_sdhc_device0 = { }; static struct resource mxc_sdhc2_resources[] = { - [0] = { - .start = SDHC2_BASE_ADDR, - .end = SDHC2_BASE_ADDR + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = MXC_INT_SDHC2, - .end = MXC_INT_SDHC2, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = DMA_REQ_SDHC2, - .end = DMA_REQ_SDHC2, - .flags = IORESOURCE_DMA - }, + { + .start = SDHC2_BASE_ADDR, + .end = SDHC2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_SDHC2, + .end = MXC_INT_SDHC2, + .flags = IORESOURCE_IRQ, + }, { + .start = DMA_REQ_SDHC2, + .end = DMA_REQ_SDHC2, + .flags = IORESOURCE_DMA, + }, }; static u64 mxc_sdhc2_dmamask = 0xffffffffUL; @@ -407,35 +437,123 @@ struct platform_device mxc_sdhc_device1 = { .resource = mxc_sdhc2_resources, }; +#ifdef CONFIG_MACH_MX27 +static struct resource otg_resources[] = { + { + .start = OTG_BASE_ADDR, + .end = OTG_BASE_ADDR + 0x1ff, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_USB3, + .end = MXC_INT_USB3, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 otg_dmamask = 0xffffffffUL; + +/* OTG gadget device */ +struct platform_device mxc_otg_udc_device = { + .name = "fsl-usb2-udc", + .id = -1, + .dev = { + .dma_mask = &otg_dmamask, + .coherent_dma_mask = 0xffffffffUL, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), +}; + +/* OTG host */ +struct platform_device mxc_otg_host = { + .name = "mxc-ehci", + .id = 0, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &otg_dmamask, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), +}; + +/* USB host 1 */ + +static u64 usbh1_dmamask = 0xffffffffUL; + +static struct resource mxc_usbh1_resources[] = { + { + .start = OTG_BASE_ADDR + 0x200, + .end = OTG_BASE_ADDR + 0x3ff, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_USB1, + .end = MXC_INT_USB1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_usbh1 = { + .name = "mxc-ehci", + .id = 1, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &usbh1_dmamask, + }, + .resource = mxc_usbh1_resources, + .num_resources = ARRAY_SIZE(mxc_usbh1_resources), +}; + +/* USB host 2 */ +static u64 usbh2_dmamask = 0xffffffffUL; + +static struct resource mxc_usbh2_resources[] = { + { + .start = OTG_BASE_ADDR + 0x400, + .end = OTG_BASE_ADDR + 0x5ff, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_USB2, + .end = MXC_INT_USB2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_usbh2 = { + .name = "mxc-ehci", + .id = 2, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &usbh2_dmamask, + }, + .resource = mxc_usbh2_resources, + .num_resources = ARRAY_SIZE(mxc_usbh2_resources), +}; +#endif + /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { - [0] = { + { .chip.label = "gpio-0", .irq = MXC_INT_GPIO, .base = IO_ADDRESS(GPIO_BASE_ADDR), .virtual_irq_start = MXC_GPIO_IRQ_START, - }, - [1] = { + }, { .chip.label = "gpio-1", .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x100), .virtual_irq_start = MXC_GPIO_IRQ_START + 32, - }, - [2] = { + }, { .chip.label = "gpio-2", .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x200), .virtual_irq_start = MXC_GPIO_IRQ_START + 64, - }, - [3] = { + }, { .chip.label = "gpio-3", .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x300), .virtual_irq_start = MXC_GPIO_IRQ_START + 96, - }, - [4] = { + }, { .chip.label = "gpio-4", .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x400), .virtual_irq_start = MXC_GPIO_IRQ_START + 128, - }, - [5] = { + }, { .chip.label = "gpio-5", .base = IO_ADDRESS(GPIO_BASE_ADDR + 0x500), .virtual_irq_start = MXC_GPIO_IRQ_START + 160, diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index 049005bb6aa9..d315406d6725 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -4,7 +4,6 @@ extern struct platform_device mxc_gpt3; extern struct platform_device mxc_gpt4; extern struct platform_device mxc_gpt5; extern struct platform_device mxc_wdt; -extern struct platform_device mxc_irda_device; extern struct platform_device mxc_uart_device0; extern struct platform_device mxc_uart_device1; extern struct platform_device mxc_uart_device2; @@ -20,3 +19,11 @@ extern struct platform_device mxc_i2c_device0; extern struct platform_device mxc_i2c_device1; extern struct platform_device mxc_sdhc_device0; extern struct platform_device mxc_sdhc_device1; +extern struct platform_device mxc_otg_udc_device; +extern struct platform_device mxc_otg_host; +extern struct platform_device mxc_usbh1; +extern struct platform_device mxc_usbh2; +extern struct platform_device mxc_spi_device0; +extern struct platform_device mxc_spi_device1; +extern struct platform_device mxc_spi_device2; + diff --git a/arch/arm/mach-mx2/eukrea_cpuimx27.c b/arch/arm/mach-mx2/eukrea_cpuimx27.c new file mode 100644 index 000000000000..7b187606682c --- /dev/null +++ b/arch/arm/mach-mx2/eukrea_cpuimx27.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2009 Eric Benard - eric@eukrea.com + * + * Based on pcm038.c which is : + * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix + * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/i2c.h> +#include <linux/io.h> +#include <linux/mtd/plat-ram.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <asm/mach/map.h> + +#include <mach/board-eukrea_cpuimx27.h> +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/i2c.h> +#include <mach/iomux.h> +#include <mach/imx-uart.h> +#include <mach/mxc_nand.h> + +#include "devices.h" + +static int eukrea_cpuimx27_pins[] = { + /* UART1 */ + PE12_PF_UART1_TXD, + PE13_PF_UART1_RXD, + PE14_PF_UART1_CTS, + PE15_PF_UART1_RTS, + /* UART4 */ + PB26_AF_UART4_RTS, + PB28_AF_UART4_TXD, + PB29_AF_UART4_CTS, + PB31_AF_UART4_RXD, + /* FEC */ + PD0_AIN_FEC_TXD0, + PD1_AIN_FEC_TXD1, + PD2_AIN_FEC_TXD2, + PD3_AIN_FEC_TXD3, + PD4_AOUT_FEC_RX_ER, + PD5_AOUT_FEC_RXD1, + PD6_AOUT_FEC_RXD2, + PD7_AOUT_FEC_RXD3, + PD8_AF_FEC_MDIO, + PD9_AIN_FEC_MDC, + PD10_AOUT_FEC_CRS, + PD11_AOUT_FEC_TX_CLK, + PD12_AOUT_FEC_RXD0, + PD13_AOUT_FEC_RX_DV, + PD14_AOUT_FEC_RX_CLK, + PD15_AOUT_FEC_COL, + PD16_AIN_FEC_TX_ER, + PF23_AIN_FEC_TX_EN, + /* I2C1 */ + PD17_PF_I2C_DATA, + PD18_PF_I2C_CLK, + /* SDHC2 */ + PB4_PF_SD2_D0, + PB5_PF_SD2_D1, + PB6_PF_SD2_D2, + PB7_PF_SD2_D3, + PB8_PF_SD2_CMD, + PB9_PF_SD2_CLK, +#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) + /* Quad UART's IRQ */ + GPIO_PORTD | 22 | GPIO_GPIO | GPIO_IN, + GPIO_PORTD | 23 | GPIO_GPIO | GPIO_IN, + GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN, + GPIO_PORTD | 30 | GPIO_GPIO | GPIO_IN, +#endif +}; + +static struct physmap_flash_data eukrea_cpuimx27_flash_data = { + .width = 2, +}; + +static struct resource eukrea_cpuimx27_flash_resource = { + .start = 0xc0000000, + .end = 0xc3ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device eukrea_cpuimx27_nor_mtd_device = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &eukrea_cpuimx27_flash_data, + }, + .num_resources = 1, + .resource = &eukrea_cpuimx27_flash_resource, +}; + +static struct imxuart_platform_data uart_pdata[] = { + { + .flags = IMXUART_HAVE_RTSCTS, + }, { + .flags = IMXUART_HAVE_RTSCTS, + }, +}; + +static struct mxc_nand_platform_data eukrea_cpuimx27_nand_board_info = { + .width = 1, + .hw_ecc = 1, +}; + +static struct platform_device *platform_devices[] __initdata = { + &eukrea_cpuimx27_nor_mtd_device, + &mxc_fec_device, +}; + +static struct imxi2c_platform_data eukrea_cpuimx27_i2c_1_data = { + .bitrate = 100000, +}; + +static struct i2c_board_info eukrea_cpuimx27_i2c_devices[] = { + { + I2C_BOARD_INFO("pcf8563", 0x51), + }, +}; + +#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) +static struct plat_serial8250_port serial_platform_data[] = { + { + .mapbase = (unsigned long)(CS3_BASE_ADDR + 0x200000), + .irq = IRQ_GPIOB(23), + .uartclk = 14745600, + .regshift = 1, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + .mapbase = (unsigned long)(CS3_BASE_ADDR + 0x400000), + .irq = IRQ_GPIOB(22), + .uartclk = 14745600, + .regshift = 1, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + .mapbase = (unsigned long)(CS3_BASE_ADDR + 0x800000), + .irq = IRQ_GPIOB(27), + .uartclk = 14745600, + .regshift = 1, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + .mapbase = (unsigned long)(CS3_BASE_ADDR + 0x1000000), + .irq = IRQ_GPIOB(30), + .uartclk = 14745600, + .regshift = 1, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, + }, { + } +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = serial_platform_data, + }, +}; +#endif + +static void __init eukrea_cpuimx27_init(void) +{ + mxc_gpio_setup_multiple_pins(eukrea_cpuimx27_pins, + ARRAY_SIZE(eukrea_cpuimx27_pins), "CPUIMX27"); + + mxc_register_device(&mxc_uart_device0, &uart_pdata[0]); + + mxc_register_device(&mxc_nand_device, &eukrea_cpuimx27_nand_board_info); + + i2c_register_board_info(0, eukrea_cpuimx27_i2c_devices, + ARRAY_SIZE(eukrea_cpuimx27_i2c_devices)); + + mxc_register_device(&mxc_i2c_device0, &eukrea_cpuimx27_i2c_1_data); + + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); + +#if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2) + /* SDHC2 can be used for Wifi */ + mxc_register_device(&mxc_sdhc_device1, NULL); + /* in which case UART4 is also used for Bluetooth */ + mxc_register_device(&mxc_uart_device3, &uart_pdata[1]); +#endif + +#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) + platform_device_register(&serial_device); +#endif + +#ifdef CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD + eukrea_mbimx27_baseboard_init(); +#endif +} + +static void __init eukrea_cpuimx27_timer_init(void) +{ + mx27_clocks_init(26000000); +} + +static struct sys_timer eukrea_cpuimx27_timer = { + .init = eukrea_cpuimx27_timer_init, +}; + +MACHINE_START(CPUIMX27, "EUKREA CPUIMX27") + .phys_io = AIPI_BASE_ADDR, + .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mx27_map_io, + .init_irq = mx27_init_irq, + .init_machine = eukrea_cpuimx27_init, + .timer = &eukrea_cpuimx27_timer, +MACHINE_END diff --git a/arch/arm/mach-mx2/eukrea_mbimx27-baseboard.c b/arch/arm/mach-mx2/eukrea_mbimx27-baseboard.c new file mode 100644 index 000000000000..7382b6d27ee1 --- /dev/null +++ b/arch/arm/mach-mx2/eukrea_mbimx27-baseboard.c @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2009 Eric Benard - eric@eukrea.com + * + * Based on pcm970-baseboard.c which is : + * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/gpio.h> +#include <linux/irq.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/spi/ads7846.h> + +#include <asm/mach/arch.h> + +#include <mach/common.h> +#include <mach/iomux.h> +#include <mach/imxfb.h> +#include <mach/hardware.h> +#include <mach/mmc.h> +#include <mach/imx-uart.h> + +#include "devices.h" + +static int eukrea_mbimx27_pins[] = { + /* UART2 */ + PE3_PF_UART2_CTS, + PE4_PF_UART2_RTS, + PE6_PF_UART2_TXD, + PE7_PF_UART2_RXD, + /* UART3 */ + PE8_PF_UART3_TXD, + PE9_PF_UART3_RXD, + PE10_PF_UART3_CTS, + PE11_PF_UART3_RTS, + /* UART4 */ + PB26_AF_UART4_RTS, + PB28_AF_UART4_TXD, + PB29_AF_UART4_CTS, + PB31_AF_UART4_RXD, + /* SDHC1*/ + PE18_PF_SD1_D0, + PE19_PF_SD1_D1, + PE20_PF_SD1_D2, + PE21_PF_SD1_D3, + PE22_PF_SD1_CMD, + PE23_PF_SD1_CLK, + /* display */ + PA5_PF_LSCLK, + PA6_PF_LD0, + PA7_PF_LD1, + PA8_PF_LD2, + PA9_PF_LD3, + PA10_PF_LD4, + PA11_PF_LD5, + PA12_PF_LD6, + PA13_PF_LD7, + PA14_PF_LD8, + PA15_PF_LD9, + PA16_PF_LD10, + PA17_PF_LD11, + PA18_PF_LD12, + PA19_PF_LD13, + PA20_PF_LD14, + PA21_PF_LD15, + PA22_PF_LD16, + PA23_PF_LD17, + PA28_PF_HSYNC, + PA29_PF_VSYNC, + PA30_PF_CONTRAST, + PA31_PF_OE_ACD, + /* SPI1 */ + PD28_PF_CSPI1_SS0, + PD29_PF_CSPI1_SCLK, + PD30_PF_CSPI1_MISO, + PD31_PF_CSPI1_MOSI, +}; + +static struct gpio_led gpio_leds[] = { + { + .name = "led1", + .default_trigger = "heartbeat", + .active_low = 1, + .gpio = GPIO_PORTF | 16, + }, + { + .name = "led2", + .default_trigger = "none", + .active_low = 1, + .gpio = GPIO_PORTF | 19, + }, + { + .name = "backlight", + .default_trigger = "backlight", + .active_low = 0, + .gpio = GPIO_PORTE | 5, + }, +}; + +static struct gpio_led_platform_data gpio_led_info = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + +static struct platform_device leds_gpio = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &gpio_led_info, + }, +}; + +static struct imx_fb_videomode eukrea_mbimx27_modes[] = { + { + .mode = { + .name = "CMO-QGVA", + .refresh = 60, + .xres = 320, + .yres = 240, + .pixclock = 156000, + .hsync_len = 30, + .left_margin = 38, + .right_margin = 20, + .vsync_len = 3, + .upper_margin = 15, + .lower_margin = 4, + }, + .pcr = 0xFAD08B80, + .bpp = 16, + }, +}; + +static struct imx_fb_platform_data eukrea_mbimx27_fb_data = { + .mode = eukrea_mbimx27_modes, + .num_modes = ARRAY_SIZE(eukrea_mbimx27_modes), + + .pwmr = 0x00A903FF, + .lscr1 = 0x00120300, + .dmacr = 0x00040060, +}; + +static struct imxuart_platform_data uart_pdata[] = { + { + .flags = IMXUART_HAVE_RTSCTS, + }, + { + .flags = IMXUART_HAVE_RTSCTS, + }, +}; + +#if defined(CONFIG_TOUCHSCREEN_ADS7846) + || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) + +#define ADS7846_PENDOWN (GPIO_PORTD | 25) + +static void ads7846_dev_init(void) +{ + if (gpio_request(ADS7846_PENDOWN, "ADS7846 pendown") < 0) { + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + return; + } + + gpio_direction_input(ADS7846_PENDOWN); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(ADS7846_PENDOWN); +} + +static struct ads7846_platform_data ads7846_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct spi_board_info eukrea_mbimx27_spi_board_info[] __initdata = { + [0] = { + .modalias = "ads7846", + .bus_num = 0, + .chip_select = 0, + .max_speed_hz = 1500000, + .irq = IRQ_GPIOD(25), + .platform_data = &ads7846_config, + .mode = SPI_MODE_2, + }, +}; + +static int eukrea_mbimx27_spi_cs[] = {GPIO_PORTD | 28}; + +static struct spi_imx_master eukrea_mbimx27_spi_0_data = { + .chipselect = eukrea_mbimx27_spi_cs, + .num_chipselect = ARRAY_SIZE(eukrea_mbimx27_spi_cs), +}; +#endif + +static struct platform_device *platform_devices[] __initdata = { + &leds_gpio, +}; + +/* + * system init for baseboard usage. Will be called by cpuimx27 init. + * + * Add platform devices present on this baseboard and init + * them from CPU side as far as required to use them later on + */ +void __init eukrea_mbimx27_baseboard_init(void) +{ + mxc_gpio_setup_multiple_pins(eukrea_mbimx27_pins, + ARRAY_SIZE(eukrea_mbimx27_pins), "MBIMX27"); + + mxc_register_device(&mxc_uart_device1, &uart_pdata[0]); + mxc_register_device(&mxc_uart_device2, &uart_pdata[1]); + + mxc_register_device(&mxc_fb_device, &eukrea_mbimx27_fb_data); + mxc_register_device(&mxc_sdhc_device0, NULL); + +#if defined(CONFIG_TOUCHSCREEN_ADS7846) + || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) + /* SPI and ADS7846 Touchscreen controler init */ + mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT); + mxc_gpio_mode(GPIO_PORTD | 25 | GPIO_GPIO | GPIO_IN); + mxc_register_device(&mxc_spi_device0, &eukrea_mbimx27_spi_0_data); + spi_register_board_info(eukrea_mbimx27_spi_board_info, + ARRAY_SIZE(eukrea_mbimx27_spi_board_info)); + ads7846_dev_init(); +#endif + + /* Leds configuration */ + mxc_gpio_mode(GPIO_PORTF | 16 | GPIO_GPIO | GPIO_OUT); + mxc_gpio_mode(GPIO_PORTF | 19 | GPIO_GPIO | GPIO_OUT); + /* Backlight */ + mxc_gpio_mode(GPIO_PORTE | 5 | GPIO_GPIO | GPIO_OUT); + + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); +} diff --git a/arch/arm/mach-mx2/generic.c b/arch/arm/mach-mx2/generic.c index 169372f69d8f..ae8f759134d1 100644 --- a/arch/arm/mach-mx2/generic.c +++ b/arch/arm/mach-mx2/generic.c @@ -72,6 +72,7 @@ static struct map_desc mxc_io_desc[] __initdata = { void __init mx21_map_io(void) { mxc_set_cpu_type(MXC_CPU_MX21); + mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR)); iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); } @@ -79,7 +80,18 @@ void __init mx21_map_io(void) void __init mx27_map_io(void) { mxc_set_cpu_type(MXC_CPU_MX27); + mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR)); iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); } +void __init mx27_init_irq(void) +{ + mxc_init_irq(IO_ADDRESS(AVIC_BASE_ADDR)); +} + +void __init mx21_init_irq(void) +{ + mx27_init_irq(); +} + diff --git a/arch/arm/mach-mx2/mx21ads.c b/arch/arm/mach-mx2/mx21ads.c index a5ee461cb405..cf5f77cbc2f1 100644 --- a/arch/arm/mach-mx2/mx21ads.c +++ b/arch/arm/mach-mx2/mx21ads.c @@ -164,25 +164,33 @@ static void mx21ads_fb_exit(struct platform_device *pdev) * Connected is a portrait Sharp-QVGA display * of type: LQ035Q7DB02 */ -static struct imx_fb_platform_data mx21ads_fb_data = { - .pixclock = 188679, /* in ps */ - .xres = 240, - .yres = 320, - - .bpp = 16, - .hsync_len = 2, - .left_margin = 6, - .right_margin = 16, +static struct imx_fb_videomode mx21ads_modes[] = { + { + .mode = { + .name = "Sharp-LQ035Q7", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 188679, /* in ps (5.3MHz) */ + .hsync_len = 2, + .left_margin = 6, + .right_margin = 16, + .vsync_len = 1, + .upper_margin = 8, + .lower_margin = 10, + }, + .pcr = 0xfb108bc7, + .bpp = 16, + }, +}; - .vsync_len = 1, - .upper_margin = 8, - .lower_margin = 10, - .fixed_screen_cpu = 0, +static struct imx_fb_platform_data mx21ads_fb_data = { + .mode = mx21ads_modes, + .num_modes = ARRAY_SIZE(mx21ads_modes), - .pcr = 0xFB108BC7, - .pwmr = 0x00A901ff, - .lscr1 = 0x00120300, - .dmacr = 0x00020008, + .pwmr = 0x00a903ff, + .lscr1 = 0x00120300, + .dmacr = 0x00020008, .init = mx21ads_fb_init, .exit = mx21ads_fb_exit, @@ -280,7 +288,7 @@ MACHINE_START(MX21ADS, "Freescale i.MX21ADS") .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx21ads_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx21_init_irq, .init_machine = mx21ads_board_init, .timer = &mx21ads_timer, MACHINE_END diff --git a/arch/arm/mach-mx2/mx27ads.c b/arch/arm/mach-mx2/mx27ads.c index 02daddac6995..83e412b713e6 100644 --- a/arch/arm/mach-mx2/mx27ads.c +++ b/arch/arm/mach-mx2/mx27ads.c @@ -183,20 +183,29 @@ void lcd_power(int on) __raw_writew(PBC_BCTRL1_LCDON, PBC_BCTRL1_CLEAR_REG); } -static struct imx_fb_platform_data mx27ads_fb_data = { - .pixclock = 188679, - .xres = 240, - .yres = 320, - - .bpp = 16, - .hsync_len = 1, - .left_margin = 9, - .right_margin = 16, +static struct imx_fb_videomode mx27ads_modes[] = { + { + .mode = { + .name = "Sharp-LQ035Q7", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 188679, /* in ps (5.3MHz) */ + .hsync_len = 1, + .left_margin = 9, + .right_margin = 16, + .vsync_len = 1, + .upper_margin = 7, + .lower_margin = 9, + }, + .bpp = 16, + .pcr = 0xFB008BC0, + }, +}; - .vsync_len = 1, - .upper_margin = 7, - .lower_margin = 9, - .fixed_screen_cpu = 0, +static struct imx_fb_platform_data mx27ads_fb_data = { + .mode = mx27ads_modes, + .num_modes = ARRAY_SIZE(mx27ads_modes), /* * - HSYNC active high @@ -207,7 +216,6 @@ static struct imx_fb_platform_data mx27ads_fb_data = { * - data enable low active * - enable sharp mode */ - .pcr = 0xFB008BC0, .pwmr = 0x00A903FF, .lscr1 = 0x00120300, .dmacr = 0x00020010, @@ -330,7 +338,7 @@ MACHINE_START(MX27ADS, "Freescale i.MX27ADS") .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx27ads_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx27_init_irq, .init_machine = mx27ads_board_init, .timer = &mx27ads_timer, MACHINE_END diff --git a/arch/arm/mach-mx2/mx27lite.c b/arch/arm/mach-mx2/mx27lite.c index 3ae11cb8c04b..82ea227ea0cf 100644 --- a/arch/arm/mach-mx2/mx27lite.c +++ b/arch/arm/mach-mx2/mx27lite.c @@ -89,7 +89,7 @@ MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE") .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx27_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx27_init_irq, .init_machine = mx27lite_init, .timer = &mx27lite_timer, MACHINE_END diff --git a/arch/arm/mach-mx2/mx27pdk.c b/arch/arm/mach-mx2/mx27pdk.c index 1d9238c7a6c3..6761d1b79e43 100644 --- a/arch/arm/mach-mx2/mx27pdk.c +++ b/arch/arm/mach-mx2/mx27pdk.c @@ -89,7 +89,7 @@ MACHINE_START(MX27_3DS, "Freescale MX27PDK") .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx27_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx27_init_irq, .init_machine = mx27pdk_init, .timer = &mx27pdk_timer, MACHINE_END diff --git a/arch/arm/mach-mx2/pca100.c b/arch/arm/mach-mx2/pca100.c new file mode 100644 index 000000000000..fe5b165b88cc --- /dev/null +++ b/arch/arm/mach-mx2/pca100.c @@ -0,0 +1,244 @@ +/* + * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix + * Copyright (C) 2009 Sascha Hauer (kernel@pengutronix.de) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/i2c.h> +#include <linux/i2c/at24.h> +#include <linux/dma-mapping.h> +#include <linux/spi/spi.h> +#include <linux/spi/eeprom.h> +#include <linux/irq.h> +#include <linux/gpio.h> + +#include <asm/mach/arch.h> +#include <asm/mach-types.h> +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/iomux.h> +#include <mach/i2c.h> +#include <asm/mach/time.h> +#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE) +#include <mach/spi.h> +#endif +#include <mach/imx-uart.h> +#include <mach/mxc_nand.h> +#include <mach/irqs.h> +#include <mach/mmc.h> + +#include "devices.h" + +static int pca100_pins[] = { + /* UART1 */ + PE12_PF_UART1_TXD, + PE13_PF_UART1_RXD, + PE14_PF_UART1_CTS, + PE15_PF_UART1_RTS, + /* SDHC */ + PB4_PF_SD2_D0, + PB5_PF_SD2_D1, + PB6_PF_SD2_D2, + PB7_PF_SD2_D3, + PB8_PF_SD2_CMD, + PB9_PF_SD2_CLK, + /* FEC */ + PD0_AIN_FEC_TXD0, + PD1_AIN_FEC_TXD1, + PD2_AIN_FEC_TXD2, + PD3_AIN_FEC_TXD3, + PD4_AOUT_FEC_RX_ER, + PD5_AOUT_FEC_RXD1, + PD6_AOUT_FEC_RXD2, + PD7_AOUT_FEC_RXD3, + PD8_AF_FEC_MDIO, + PD9_AIN_FEC_MDC, + PD10_AOUT_FEC_CRS, + PD11_AOUT_FEC_TX_CLK, + PD12_AOUT_FEC_RXD0, + PD13_AOUT_FEC_RX_DV, + PD14_AOUT_FEC_RX_CLK, + PD15_AOUT_FEC_COL, + PD16_AIN_FEC_TX_ER, + PF23_AIN_FEC_TX_EN, + /* SSI1 */ + PC20_PF_SSI1_FS, + PC21_PF_SSI1_RXD, + PC22_PF_SSI1_TXD, + PC23_PF_SSI1_CLK, + /* onboard I2C */ + PC5_PF_I2C2_SDA, + PC6_PF_I2C2_SCL, + /* external I2C */ + PD17_PF_I2C_DATA, + PD18_PF_I2C_CLK, + /* SPI1 */ + PD25_PF_CSPI1_RDY, + PD29_PF_CSPI1_SCLK, + PD30_PF_CSPI1_MISO, + PD31_PF_CSPI1_MOSI, +}; + +static struct imxuart_platform_data uart_pdata = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static struct mxc_nand_platform_data pca100_nand_board_info = { + .width = 1, + .hw_ecc = 1, +}; + +static struct platform_device *platform_devices[] __initdata = { + &mxc_w1_master_device, + &mxc_fec_device, +}; + +static struct imxi2c_platform_data pca100_i2c_1_data = { + .bitrate = 100000, +}; + +static struct at24_platform_data board_eeprom = { + .byte_len = 4096, + .page_size = 32, + .flags = AT24_FLAG_ADDR16, +}; + +static struct i2c_board_info pca100_i2c_devices[] = { + { + I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ + .platform_data = &board_eeprom, + }, { + I2C_BOARD_INFO("rtc-pcf8563", 0x51), + .type = "pcf8563" + }, { + I2C_BOARD_INFO("lm75", 0x4a), + .type = "lm75" + } +}; + +#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE) +static struct spi_eeprom at25320 = { + .name = "at25320an", + .byte_len = 4096, + .page_size = 32, + .flags = EE_ADDR2, +}; + +static struct spi_board_info pca100_spi_board_info[] __initdata = { + { + .modalias = "at25", + .max_speed_hz = 30000, + .bus_num = 0, + .chip_select = 1, + .platform_data = &at25320, + }, +}; + +static int pca100_spi_cs[] = {GPIO_PORTD + 28, GPIO_PORTD + 27}; + +static struct spi_imx_master pca100_spi_0_data = { + .chipselect = pca100_spi_cs, + .num_chipselect = ARRAY_SIZE(pca100_spi_cs), +}; +#endif + +static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq, + void *data) +{ + int ret; + + ret = request_irq(IRQ_GPIOC(29), detect_irq, + IRQF_DISABLED | IRQF_TRIGGER_FALLING, + "imx-mmc-detect", data); + if (ret) + printk(KERN_ERR + "pca100: Failed to reuest irq for sd/mmc detection\n"); + + return ret; +} + +static void pca100_sdhc2_exit(struct device *dev, void *data) +{ + free_irq(IRQ_GPIOC(29), data); +} + +static struct imxmmc_platform_data sdhc_pdata = { + .init = pca100_sdhc2_init, + .exit = pca100_sdhc2_exit, +}; + +static void __init pca100_init(void) +{ + int ret; + + ret = mxc_gpio_setup_multiple_pins(pca100_pins, + ARRAY_SIZE(pca100_pins), "PCA100"); + if (ret) + printk(KERN_ERR "pca100: Failed to setup pins (%d)\n", ret); + + mxc_register_device(&mxc_uart_device0, &uart_pdata); + + mxc_gpio_mode(GPIO_PORTC | 29 | GPIO_GPIO | GPIO_IN); + mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata); + + mxc_register_device(&mxc_nand_device, &pca100_nand_board_info); + + /* only the i2c master 1 is used on this CPU card */ + i2c_register_board_info(1, pca100_i2c_devices, + ARRAY_SIZE(pca100_i2c_devices)); + + mxc_register_device(&mxc_i2c_device1, &pca100_i2c_1_data); + + mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT); + mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_OUT); + + /* GPIO0_IRQ */ + mxc_gpio_mode(GPIO_PORTC | 31 | GPIO_GPIO | GPIO_IN); + /* GPIO1_IRQ */ + mxc_gpio_mode(GPIO_PORTC | 25 | GPIO_GPIO | GPIO_IN); + /* GPIO2_IRQ */ + mxc_gpio_mode(GPIO_PORTE | 5 | GPIO_GPIO | GPIO_IN); + +#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE) + spi_register_board_info(pca100_spi_board_info, + ARRAY_SIZE(pca100_spi_board_info)); + mxc_register_device(&mxc_spi_device0, &pca100_spi_0_data); +#endif + + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); +} + +static void __init pca100_timer_init(void) +{ + mx27_clocks_init(26000000); +} + +static struct sys_timer pca100_timer = { + .init = pca100_timer_init, +}; + +MACHINE_START(PCA100, "phyCARD-i.MX27") + .phys_io = AIPI_BASE_ADDR, + .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mx27_map_io, + .init_irq = mxc_init_irq, + .init_machine = pca100_init, + .timer = &pca100_timer, +MACHINE_END + diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index a4628d004343..ee65dda584cf 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -186,17 +186,13 @@ static struct at24_platform_data board_eeprom = { }; static struct i2c_board_info pcm038_i2c_devices[] = { - [0] = { + { I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ .platform_data = &board_eeprom, - }, - [1] = { - I2C_BOARD_INFO("rtc-pcf8563", 0x51), - .type = "pcf8563" - }, - [2] = { + }, { + I2C_BOARD_INFO("pcf8563", 0x51), + }, { I2C_BOARD_INFO("lm75", 0x4a), - .type = "lm75" } }; @@ -220,6 +216,9 @@ static void __init pcm038_init(void) mxc_register_device(&mxc_i2c_device1, &pcm038_i2c_1_data); + /* PE18 for user-LED D40 */ + mxc_gpio_mode(GPIO_PORTE | 18 | GPIO_GPIO | GPIO_OUT); + platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); #ifdef CONFIG_MACH_PCM970_BASEBOARD @@ -241,7 +240,7 @@ MACHINE_START(PCM038, "phyCORE-i.MX27") .io_pg_offst = ((AIPI_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx27_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx27_init_irq, .init_machine = pcm038_init, .timer = &pcm038_timer, MACHINE_END diff --git a/arch/arm/mach-mx2/pcm970-baseboard.c b/arch/arm/mach-mx2/pcm970-baseboard.c index 6a3acaf57dd4..c261f59b0b4c 100644 --- a/arch/arm/mach-mx2/pcm970-baseboard.c +++ b/arch/arm/mach-mx2/pcm970-baseboard.c @@ -19,6 +19,7 @@ #include <linux/gpio.h> #include <linux/irq.h> #include <linux/platform_device.h> +#include <linux/can/platform/sja1000.h> #include <asm/mach/arch.h> @@ -125,40 +126,96 @@ static struct imxmmc_platform_data sdhc_pdata = { .exit = pcm970_sdhc2_exit, }; -/* - * Connected is a portrait Sharp-QVGA display - * of type: LQ035Q7DH06 - */ -static struct imx_fb_platform_data pcm038_fb_data = { - .pixclock = 188679, /* in ps (5.3MHz) */ - .xres = 240, - .yres = 320, - - .bpp = 16, - .hsync_len = 7, - .left_margin = 5, - .right_margin = 16, +static struct imx_fb_videomode pcm970_modes[] = { + { + .mode = { + .name = "Sharp-LQ035Q7", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 188679, /* in ps (5.3MHz) */ + .hsync_len = 7, + .left_margin = 5, + .right_margin = 16, + .vsync_len = 1, + .upper_margin = 7, + .lower_margin = 9, + }, + /* + * - HSYNC active high + * - VSYNC active high + * - clk notenabled while idle + * - clock not inverted + * - data not inverted + * - data enable low active + * - enable sharp mode + */ + .pcr = 0xF00080C0, + .bpp = 16, + }, { + .mode = { + .name = "TX090", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 38255, + .left_margin = 144, + .right_margin = 0, + .upper_margin = 7, + .lower_margin = 40, + .hsync_len = 96, + .vsync_len = 1, + }, + /* + * - HSYNC active low (1 << 22) + * - VSYNC active low (1 << 23) + * - clk notenabled while idle + * - clock not inverted + * - data not inverted + * - data enable low active + * - enable sharp mode + */ + .pcr = 0xF0008080 | (1<<22) | (1<<23) | (1<<19), + .bpp = 32, + }, +}; - .vsync_len = 1, - .upper_margin = 7, - .lower_margin = 9, - .fixed_screen_cpu = 0, +static struct imx_fb_platform_data pcm038_fb_data = { + .mode = pcm970_modes, + .num_modes = ARRAY_SIZE(pcm970_modes), - /* - * - HSYNC active high - * - VSYNC active high - * - clk notenabled while idle - * - clock not inverted - * - data not inverted - * - data enable low active - * - enable sharp mode - */ - .pcr = 0xFA0080C0, .pwmr = 0x00A903FF, .lscr1 = 0x00120300, .dmacr = 0x00020010, }; +static struct resource pcm970_sja1000_resources[] = { + { + .start = CS4_BASE_ADDR, + .end = CS4_BASE_ADDR + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_GPIOE(19), + .end = IRQ_GPIOE(19), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, + }, +}; + +struct sja1000_platform_data pcm970_sja1000_platform_data = { + .clock = 16000000 / 2, + .ocr = 0x40 | 0x18, + .cdr = 0x40, +}; + +static struct platform_device pcm970_sja1000 = { + .name = "sja1000_platform", + .dev = { + .platform_data = &pcm970_sja1000_platform_data, + }, + .resource = pcm970_sja1000_resources, + .num_resources = ARRAY_SIZE(pcm970_sja1000_resources), +}; + /* * system init for baseboard usage. Will be called by pcm038 init. * @@ -172,4 +229,5 @@ void __init pcm970_baseboard_init(void) mxc_register_device(&mxc_fb_device, &pcm038_fb_data); mxc_register_device(&mxc_sdhc_device1, &sdhc_pdata); + platform_device_register(&pcm970_sja1000); } diff --git a/arch/arm/mach-mx25/Kconfig b/arch/arm/mach-mx25/Kconfig new file mode 100644 index 000000000000..cc28f56eae80 --- /dev/null +++ b/arch/arm/mach-mx25/Kconfig @@ -0,0 +1,9 @@ +if ARCH_MX25 + +comment "MX25 platforms:" + +config MACH_MX25_3DS + select ARCH_MXC_IOMUX_V3 + bool "Support MX25PDK (3DS) Platform" + +endif diff --git a/arch/arm/mach-mx25/Makefile b/arch/arm/mach-mx25/Makefile new file mode 100644 index 000000000000..fe23836a9f3d --- /dev/null +++ b/arch/arm/mach-mx25/Makefile @@ -0,0 +1,3 @@ +obj-y := mm.o devices.o +obj-$(CONFIG_ARCH_MX25) += clock.o +obj-$(CONFIG_MACH_MX25_3DS) += mx25pdk.o diff --git a/arch/arm/mach-mx25/Makefile.boot b/arch/arm/mach-mx25/Makefile.boot new file mode 100644 index 000000000000..e1dd366f836b --- /dev/null +++ b/arch/arm/mach-mx25/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x80008000 +params_phys-y := 0x80000100 +initrd_phys-y := 0x80800000 diff --git a/arch/arm/mach-mx25/clock.c b/arch/arm/mach-mx25/clock.c new file mode 100644 index 000000000000..ef26951a5275 --- /dev/null +++ b/arch/arm/mach-mx25/clock.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2009 by Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/clk.h> +#include <linux/io.h> + +#include <asm/clkdev.h> + +#include <mach/clock.h> +#include <mach/hardware.h> +#include <mach/common.h> +#include <mach/mx25.h> + +#define CRM_BASE MX25_IO_ADDRESS(MX25_CRM_BASE_ADDR) + +#define CCM_MPCTL 0x00 +#define CCM_UPCTL 0x04 +#define CCM_CCTL 0x08 +#define CCM_CGCR0 0x0C +#define CCM_CGCR1 0x10 +#define CCM_CGCR2 0x14 +#define CCM_PCDR0 0x18 +#define CCM_PCDR1 0x1C +#define CCM_PCDR2 0x20 +#define CCM_PCDR3 0x24 +#define CCM_RCSR 0x28 +#define CCM_CRDR 0x2C +#define CCM_DCVR0 0x30 +#define CCM_DCVR1 0x34 +#define CCM_DCVR2 0x38 +#define CCM_DCVR3 0x3c +#define CCM_LTR0 0x40 +#define CCM_LTR1 0x44 +#define CCM_LTR2 0x48 +#define CCM_LTR3 0x4c + +static unsigned long get_rate_mpll(void) +{ + ulong mpctl = __raw_readl(CRM_BASE + CCM_MPCTL); + + return mxc_decode_pll(mpctl, 24000000); +} + +static unsigned long get_rate_upll(void) +{ + ulong mpctl = __raw_readl(CRM_BASE + CCM_UPCTL); + + return mxc_decode_pll(mpctl, 24000000); +} + +unsigned long get_rate_arm(struct clk *clk) +{ + unsigned long cctl = readl(CRM_BASE + CCM_CCTL); + unsigned long rate = get_rate_mpll(); + + if (cctl & (1 << 14)) + rate = (rate * 3) >> 1; + + return rate / ((cctl >> 30) + 1); +} + +static unsigned long get_rate_ahb(struct clk *clk) +{ + unsigned long cctl = readl(CRM_BASE + CCM_CCTL); + + return get_rate_arm(NULL) / (((cctl >> 28) & 0x3) + 1); +} + +static unsigned long get_rate_ipg(struct clk *clk) +{ + return get_rate_ahb(NULL) >> 1; +} + +static unsigned long get_rate_per(int per) +{ + unsigned long ofs = (per & 0x3) * 8; + unsigned long reg = per & ~0x3; + unsigned long val = (readl(CRM_BASE + CCM_PCDR0 + reg) >> ofs) & 0x3f; + unsigned long fref; + + if (readl(CRM_BASE + 0x64) & (1 << per)) + fref = get_rate_upll(); + else + fref = get_rate_ipg(NULL); + + return fref / (val + 1); +} + +static unsigned long get_rate_uart(struct clk *clk) +{ + return get_rate_per(15); +} + +static unsigned long get_rate_i2c(struct clk *clk) +{ + return get_rate_per(6); +} + +static unsigned long get_rate_nfc(struct clk *clk) +{ + return get_rate_per(8); +} + +static unsigned long get_rate_otg(struct clk *clk) +{ + return 48000000; /* FIXME */ +} + +static int clk_cgcr_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void clk_cgcr_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +#define DEFINE_CLOCK(name, i, er, es, gr, sr) \ + static struct clk name = { \ + .id = i, \ + .enable_reg = CRM_BASE + er, \ + .enable_shift = es, \ + .get_rate = gr, \ + .set_rate = sr, \ + .enable = clk_cgcr_enable, \ + .disable = clk_cgcr_disable, \ + } + +DEFINE_CLOCK(gpt_clk, 0, CCM_CGCR0, 5, get_rate_ipg, NULL); +DEFINE_CLOCK(cspi1_clk, 0, CCM_CGCR1, 5, get_rate_ipg, NULL); +DEFINE_CLOCK(cspi2_clk, 0, CCM_CGCR1, 6, get_rate_ipg, NULL); +DEFINE_CLOCK(cspi3_clk, 0, CCM_CGCR1, 7, get_rate_ipg, NULL); +DEFINE_CLOCK(uart1_clk, 0, CCM_CGCR2, 14, get_rate_uart, NULL); +DEFINE_CLOCK(uart2_clk, 0, CCM_CGCR2, 15, get_rate_uart, NULL); +DEFINE_CLOCK(uart3_clk, 0, CCM_CGCR2, 16, get_rate_uart, NULL); +DEFINE_CLOCK(uart4_clk, 0, CCM_CGCR2, 17, get_rate_uart, NULL); +DEFINE_CLOCK(uart5_clk, 0, CCM_CGCR2, 18, get_rate_uart, NULL); +DEFINE_CLOCK(nfc_clk, 0, CCM_CGCR0, 8, get_rate_nfc, NULL); +DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, NULL); +DEFINE_CLOCK(pwm1_clk, 0, CCM_CGCR1, 31, get_rate_ipg, NULL); +DEFINE_CLOCK(pwm2_clk, 0, CCM_CGCR2, 0, get_rate_ipg, NULL); +DEFINE_CLOCK(pwm3_clk, 0, CCM_CGCR2, 1, get_rate_ipg, NULL); +DEFINE_CLOCK(pwm4_clk, 0, CCM_CGCR2, 2, get_rate_ipg, NULL); +DEFINE_CLOCK(kpp_clk, 0, CCM_CGCR1, 28, get_rate_ipg, NULL); +DEFINE_CLOCK(tsc_clk, 0, CCM_CGCR2, 13, get_rate_ipg, NULL); +DEFINE_CLOCK(i2c_clk, 0, CCM_CGCR0, 6, get_rate_i2c, NULL); + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] = { + _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) + _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) + _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) + _REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk) + _REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk) + _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk) + _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk) + _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk) + _REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk) + _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk) + _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk) + _REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk) + _REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk) + _REGISTER_CLOCK("mx25-adc", NULL, tsc_clk) + _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk) + _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk) + _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk) +}; + +int __init mx25_clocks_init(unsigned long fref) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + + mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54); + + return 0; +} diff --git a/arch/arm/mach-mx25/devices.c b/arch/arm/mach-mx25/devices.c new file mode 100644 index 000000000000..eb12de1da42d --- /dev/null +++ b/arch/arm/mach-mx25/devices.c @@ -0,0 +1,402 @@ +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <mach/mx25.h> +#include <mach/irqs.h> + +static struct resource uart0[] = { + { + .start = 0x43f90000, + .end = 0x43f93fff, + .flags = IORESOURCE_MEM, + }, { + .start = 45, + .end = 45, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_uart_device0 = { + .name = "imx-uart", + .id = 0, + .resource = uart0, + .num_resources = ARRAY_SIZE(uart0), +}; + +static struct resource uart1[] = { + { + .start = 0x43f94000, + .end = 0x43f97fff, + .flags = IORESOURCE_MEM, + }, { + .start = 32, + .end = 32, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_uart_device1 = { + .name = "imx-uart", + .id = 1, + .resource = uart1, + .num_resources = ARRAY_SIZE(uart1), +}; + +static struct resource uart2[] = { + { + .start = 0x5000c000, + .end = 0x5000ffff, + .flags = IORESOURCE_MEM, + }, { + .start = 18, + .end = 18, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_uart_device2 = { + .name = "imx-uart", + .id = 2, + .resource = uart2, + .num_resources = ARRAY_SIZE(uart2), +}; + +static struct resource uart3[] = { + { + .start = 0x50008000, + .end = 0x5000bfff, + .flags = IORESOURCE_MEM, + }, { + .start = 5, + .end = 5, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_uart_device3 = { + .name = "imx-uart", + .id = 3, + .resource = uart3, + .num_resources = ARRAY_SIZE(uart3), +}; + +static struct resource uart4[] = { + { + .start = 0x5002c000, + .end = 0x5002ffff, + .flags = IORESOURCE_MEM, + }, { + .start = 40, + .end = 40, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_uart_device4 = { + .name = "imx-uart", + .id = 4, + .resource = uart4, + .num_resources = ARRAY_SIZE(uart4), +}; + +#define MX25_OTG_BASE_ADDR 0x53FF4000 + +static u64 otg_dmamask = DMA_BIT_MASK(32); + +static struct resource mxc_otg_resources[] = { + { + .start = MX25_OTG_BASE_ADDR, + .end = MX25_OTG_BASE_ADDR + 0x1ff, + .flags = IORESOURCE_MEM, + }, { + .start = 37, + .end = 37, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_otg = { + .name = "mxc-ehci", + .id = 0, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &otg_dmamask, + }, + .resource = mxc_otg_resources, + .num_resources = ARRAY_SIZE(mxc_otg_resources), +}; + +/* OTG gadget device */ +struct platform_device otg_udc_device = { + .name = "fsl-usb2-udc", + .id = -1, + .dev = { + .dma_mask = &otg_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = mxc_otg_resources, + .num_resources = ARRAY_SIZE(mxc_otg_resources), +}; + +static u64 usbh2_dmamask = DMA_BIT_MASK(32); + +static struct resource mxc_usbh2_resources[] = { + { + .start = MX25_OTG_BASE_ADDR + 0x400, + .end = MX25_OTG_BASE_ADDR + 0x5ff, + .flags = IORESOURCE_MEM, + }, { + .start = 35, + .end = 35, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_usbh2 = { + .name = "mxc-ehci", + .id = 1, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &usbh2_dmamask, + }, + .resource = mxc_usbh2_resources, + .num_resources = ARRAY_SIZE(mxc_usbh2_resources), +}; + +static struct resource mxc_spi_resources0[] = { + { + .start = 0x43fa4000, + .end = 0x43fa7fff, + .flags = IORESOURCE_MEM, + }, { + .start = 14, + .end = 14, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_spi_device0 = { + .name = "spi_imx", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_spi_resources0), + .resource = mxc_spi_resources0, +}; + +static struct resource mxc_spi_resources1[] = { + { + .start = 0x50010000, + .end = 0x50013fff, + .flags = IORESOURCE_MEM, + }, { + .start = 13, + .end = 13, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_spi_device1 = { + .name = "spi_imx", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_spi_resources1), + .resource = mxc_spi_resources1, +}; + +static struct resource mxc_spi_resources2[] = { + { + .start = 0x50004000, + .end = 0x50007fff, + .flags = IORESOURCE_MEM, + }, { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_spi_device2 = { + .name = "spi_imx", + .id = 2, + .num_resources = ARRAY_SIZE(mxc_spi_resources2), + .resource = mxc_spi_resources2, +}; + +static struct resource mxc_pwm_resources0[] = { + { + .start = 0x53fe0000, + .end = 0x53fe3fff, + .flags = IORESOURCE_MEM, + }, { + .start = 26, + .end = 26, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_pwm_device0 = { + .name = "mxc_pwm", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_pwm_resources0), + .resource = mxc_pwm_resources0, +}; + +static struct resource mxc_pwm_resources1[] = { + { + .start = 0x53fa0000, + .end = 0x53fa3fff, + .flags = IORESOURCE_MEM, + }, { + .start = 36, + .end = 36, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_pwm_device1 = { + .name = "mxc_pwm", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_pwm_resources1), + .resource = mxc_pwm_resources1, +}; + +static struct resource mxc_pwm_resources2[] = { + { + .start = 0x53fa8000, + .end = 0x53fabfff, + .flags = IORESOURCE_MEM, + }, { + .start = 41, + .end = 41, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_pwm_device2 = { + .name = "mxc_pwm", + .id = 2, + .num_resources = ARRAY_SIZE(mxc_pwm_resources2), + .resource = mxc_pwm_resources2, +}; + +static struct resource mxc_keypad_resources[] = { + { + .start = 0x43fa8000, + .end = 0x43fabfff, + .flags = IORESOURCE_MEM, + }, { + .start = 24, + .end = 24, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_keypad_device = { + .name = "mxc-keypad", + .id = -1, + .num_resources = ARRAY_SIZE(mxc_keypad_resources), + .resource = mxc_keypad_resources, +}; + +static struct resource mxc_pwm_resources3[] = { + { + .start = 0x53fc8000, + .end = 0x53fcbfff, + .flags = IORESOURCE_MEM, + }, { + .start = 42, + .end = 42, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_pwm_device3 = { + .name = "mxc_pwm", + .id = 3, + .num_resources = ARRAY_SIZE(mxc_pwm_resources3), + .resource = mxc_pwm_resources3, +}; + +static struct resource mxc_i2c_1_resources[] = { + { + .start = 0x43f80000, + .end = 0x43f83fff, + .flags = IORESOURCE_MEM, + }, { + .start = 3, + .end = 3, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_i2c_device0 = { + .name = "imx-i2c", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_i2c_1_resources), + .resource = mxc_i2c_1_resources, +}; + +static struct resource mxc_i2c_2_resources[] = { + { + .start = 0x43f98000, + .end = 0x43f9bfff, + .flags = IORESOURCE_MEM, + }, { + .start = 4, + .end = 4, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_i2c_device1 = { + .name = "imx-i2c", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_i2c_2_resources), + .resource = mxc_i2c_2_resources, +}; + +static struct resource mxc_i2c_3_resources[] = { + { + .start = 0x43f84000, + .end = 0x43f87fff, + .flags = IORESOURCE_MEM, + }, { + .start = 10, + .end = 10, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device mxc_i2c_device2 = { + .name = "imx-i2c", + .id = 2, + .num_resources = ARRAY_SIZE(mxc_i2c_3_resources), + .resource = mxc_i2c_3_resources, +}; + +static struct mxc_gpio_port imx_gpio_ports[] = { + { + .chip.label = "gpio-0", + .base = (void __iomem *)MX25_GPIO1_BASE_ADDR_VIRT, + .irq = 52, + .virtual_irq_start = MXC_GPIO_IRQ_START, + }, { + .chip.label = "gpio-1", + .base = (void __iomem *)MX25_GPIO2_BASE_ADDR_VIRT, + .irq = 51, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32, + }, { + .chip.label = "gpio-2", + .base = (void __iomem *)MX25_GPIO3_BASE_ADDR_VIRT, + .irq = 16, + .virtual_irq_start = MXC_GPIO_IRQ_START + 64, + }, { + .chip.label = "gpio-3", + .base = (void __iomem *)MX25_GPIO4_BASE_ADDR_VIRT, + .irq = 23, + .virtual_irq_start = MXC_GPIO_IRQ_START + 96, + } +}; + +int __init mxc_register_gpios(void) +{ + return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports)); +} + diff --git a/arch/arm/mach-mx25/devices.h b/arch/arm/mach-mx25/devices.h new file mode 100644 index 000000000000..fe6bf88ad1dd --- /dev/null +++ b/arch/arm/mach-mx25/devices.h @@ -0,0 +1,19 @@ +extern struct platform_device mxc_uart_device0; +extern struct platform_device mxc_uart_device1; +extern struct platform_device mxc_uart_device2; +extern struct platform_device mxc_uart_device3; +extern struct platform_device mxc_uart_device4; +extern struct platform_device mxc_otg; +extern struct platform_device otg_udc_device; +extern struct platform_device mxc_usbh2; +extern struct platform_device mxc_spi_device0; +extern struct platform_device mxc_spi_device1; +extern struct platform_device mxc_spi_device2; +extern struct platform_device mxc_pwm_device0; +extern struct platform_device mxc_pwm_device1; +extern struct platform_device mxc_pwm_device2; +extern struct platform_device mxc_pwm_device3; +extern struct platform_device mxc_keypad_device; +extern struct platform_device mxc_i2c_device0; +extern struct platform_device mxc_i2c_device1; +extern struct platform_device mxc_i2c_device2; diff --git a/arch/arm/mach-mx25/mm.c b/arch/arm/mach-mx25/mm.c new file mode 100644 index 000000000000..a7e587ff3e9e --- /dev/null +++ b/arch/arm/mach-mx25/mm.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 1999,2000 Arm Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * Copyright (C) 2002 Shane Nay (shane@minirl.com) + * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * - add MX31 specific definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/err.h> + +#include <asm/pgtable.h> +#include <asm/mach/map.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/mx25.h> +#include <mach/iomux-v3.h> + +/* + * This table defines static virtual address mappings for I/O regions. + * These are the mappings common across all MX3 boards. + */ +static struct map_desc mxc_io_desc[] __initdata = { + { + .virtual = MX25_AVIC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MX25_AVIC_BASE_ADDR), + .length = MX25_AVIC_SIZE, + .type = MT_DEVICE_NONSHARED + }, { + .virtual = MX25_AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MX25_AIPS1_BASE_ADDR), + .length = MX25_AIPS1_SIZE, + .type = MT_DEVICE_NONSHARED + }, { + .virtual = MX25_AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MX25_AIPS2_BASE_ADDR), + .length = MX25_AIPS2_SIZE, + .type = MT_DEVICE_NONSHARED + }, +}; + +/* + * This function initializes the memory map. It is called during the + * system startup to create static physical to virtual memory mappings + * for the IO modules. + */ +void __init mx25_map_io(void) +{ + mxc_set_cpu_type(MXC_CPU_MX25); + mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR)); + mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR)); + + iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); +} + +void __init mx25_init_irq(void) +{ + mxc_init_irq((void __iomem *)MX25_AVIC_BASE_ADDR_VIRT); +} + diff --git a/arch/arm/mach-mx25/mx25pdk.c b/arch/arm/mach-mx25/mx25pdk.c new file mode 100644 index 000000000000..92aa4fd19d99 --- /dev/null +++ b/arch/arm/mach-mx25/mx25pdk.c @@ -0,0 +1,58 @@ +#include <linux/types.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/smsc911x.h> +#include <linux/platform_device.h> + +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/time.h> +#include <asm/memory.h> +#include <asm/mach/map.h> +#include <mach/common.h> +#include <mach/imx-uart.h> +#include <mach/mx25.h> +#include <mach/mxc_nand.h> +#include "devices.h" +#include <mach/iomux-v3.h> + +static struct imxuart_platform_data uart_pdata = { + .flags = IMXUART_HAVE_RTSCTS, +}; + +static struct mxc_nand_platform_data nand_board_info = { + .width = 1, + .hw_ecc = 1, +}; + +static void __init mx25pdk_init(void) +{ + mxc_register_device(&mxc_uart_device0, &uart_pdata); + mxc_register_device(&mxc_usbh2, NULL); + mxc_register_device(&mxc_nand_device, &nand_board_info); +} + + +static void __init mx25pdk_timer_init(void) +{ + mx25_clocks_init(26000000); +} + +static struct sys_timer mx25pdk_timer = { + .init = mx25pdk_timer_init, +}; + +MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)") + /* Maintainer: Freescale Semiconductor, Inc. */ + .phys_io = MX25_AIPS1_BASE_ADDR, + .io_pg_offst = ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mx25_map_io, + .init_irq = mx25_init_irq, + .init_machine = mx25pdk_init, + .timer = &mx25pdk_timer, +MACHINE_END + diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index 17a21a291e2f..851f2458bf65 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -36,6 +36,14 @@ config MACH_PCM037 Include support for Phytec pcm037 platform. This includes specific configurations for the board and its peripherals. +config MACH_PCM037_EET + bool "Support pcm037 EET board extensions" + depends on MACH_PCM037 + help + Add support for PCM037 EET baseboard extensions. If you are using the + OLED display with EET, use "video=mx3fb:CMEL-OLED" kernel + command-line parameter. + config MACH_MX31LITE bool "Support MX31 LITEKIT (LogicPD)" select ARCH_MX31 diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile index 0322696bd11a..6b9775471be6 100644 --- a/arch/arm/mach-mx3/Makefile +++ b/arch/arm/mach-mx3/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_MACH_MX31ADS) += mx31ads.o obj-$(CONFIG_MACH_MX31LILLY) += mx31lilly.o mx31lilly-db.o obj-$(CONFIG_MACH_MX31LITE) += mx31lite.o obj-$(CONFIG_MACH_PCM037) += pcm037.o +obj-$(CONFIG_MACH_PCM037_EET) += pcm037_eet.o obj-$(CONFIG_MACH_MX31_3DS) += mx31pdk.o obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o mx31moboard-devboard.o \ mx31moboard-marxbot.o diff --git a/arch/arm/mach-mx3/armadillo5x0.c b/arch/arm/mach-mx3/armadillo5x0.c index 541181090b37..776c0ee1b3cd 100644 --- a/arch/arm/mach-mx3/armadillo5x0.c +++ b/arch/arm/mach-mx3/armadillo5x0.c @@ -31,6 +31,8 @@ #include <linux/smsc911x.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/io.h> #include <mach/hardware.h> #include <asm/mach-types.h> @@ -46,8 +48,10 @@ #include <mach/mmc.h> #include <mach/ipu.h> #include <mach/mx3fb.h> +#include <mach/mxc_nand.h> #include "devices.h" +#include "crm_regs.h" static int armadillo5x0_pins[] = { /* UART1 */ @@ -93,7 +97,56 @@ static int armadillo5x0_pins[] = { MX31_PIN_FPSHIFT__FPSHIFT, MX31_PIN_DRDY0__DRDY0, IOMUX_MODE(MX31_PIN_LCS1, IOMUX_CONFIG_GPIO), /*ADV7125_PSAVE*/ +}; +/* + * NAND Flash + */ +static struct mxc_nand_platform_data armadillo5x0_nand_flash_pdata = { + .width = 1, + .hw_ecc = 1, +}; + +/* + * MTD NOR Flash + */ +static struct mtd_partition armadillo5x0_nor_flash_partitions[] = { + { + .name = "nor.bootloader", + .offset = 0x00000000, + .size = 4*32*1024, + }, { + .name = "nor.kernel", + .offset = MTDPART_OFS_APPEND, + .size = 16*128*1024, + }, { + .name = "nor.userland", + .offset = MTDPART_OFS_APPEND, + .size = 110*128*1024, + }, { + .name = "nor.config", + .offset = MTDPART_OFS_APPEND, + .size = 1*128*1024, + }, +}; + +static struct physmap_flash_data armadillo5x0_nor_flash_pdata = { + .width = 2, + .parts = armadillo5x0_nor_flash_partitions, + .nr_parts = ARRAY_SIZE(armadillo5x0_nor_flash_partitions), +}; + +static struct resource armadillo5x0_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = CS0_BASE_ADDR, + .end = CS0_BASE_ADDR + SZ_64M - 1, +}; + +static struct platform_device armadillo5x0_nor_flash = { + .name = "physmap-flash", + .id = -1, + .num_resources = 1, + .resource = &armadillo5x0_nor_flash_resource, }; /* @@ -272,6 +325,16 @@ static void __init armadillo5x0_init(void) /* Register FB */ mxc_register_device(&mx3_ipu, &mx3_ipu_data); mxc_register_device(&mx3_fb, &mx3fb_pdata); + + /* Register NOR Flash */ + mxc_register_device(&armadillo5x0_nor_flash, + &armadillo5x0_nor_flash_pdata); + + /* Register NAND Flash */ + mxc_register_device(&mxc_nand_device, &armadillo5x0_nand_flash_pdata); + + /* set NAND page size to 2k if not configured via boot mode pins */ + __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR); } static void __init armadillo5x0_timer_init(void) @@ -289,7 +352,7 @@ MACHINE_START(ARMADILLO5X0, "Armadillo-500") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x00000100, .map_io = mx31_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx31_init_irq, .timer = &armadillo5x0_timer, .init_machine = armadillo5x0_init, MACHINE_END diff --git a/arch/arm/mach-mx3/clock-imx35.c b/arch/arm/mach-mx3/clock-imx35.c index 577ee83d1f60..fe5c4217322e 100644 --- a/arch/arm/mach-mx3/clock-imx35.c +++ b/arch/arm/mach-mx3/clock-imx35.c @@ -273,6 +273,19 @@ static unsigned long get_rate_csi(struct clk *clk) return rate / get_3_3_div((pdr2 >> 16) & 0x3f); } +static unsigned long get_rate_otg(struct clk *clk) +{ + unsigned long pdr4 = __raw_readl(CCM_BASE + CCM_PDR4); + unsigned long rate; + + if (pdr4 & (1 << 9)) + rate = get_rate_arm(); + else + rate = get_rate_ppll(); + + return rate / get_3_3_div((pdr4 >> 22) & 0x3f); +} + static unsigned long get_rate_ipg_per(struct clk *clk) { unsigned long pdr0 = __raw_readl(CCM_BASE + CCM_PDR0); @@ -365,7 +378,7 @@ DEFINE_CLOCK(ssi2_clk, 1, CCM_CGR2, 14, get_rate_ssi, NULL); DEFINE_CLOCK(uart1_clk, 0, CCM_CGR2, 16, get_rate_uart, NULL); DEFINE_CLOCK(uart2_clk, 1, CCM_CGR2, 18, get_rate_uart, NULL); DEFINE_CLOCK(uart3_clk, 2, CCM_CGR2, 20, get_rate_uart, NULL); -DEFINE_CLOCK(usbotg_clk, 0, CCM_CGR2, 22, NULL, NULL); +DEFINE_CLOCK(usbotg_clk, 0, CCM_CGR2, 22, get_rate_otg, NULL); DEFINE_CLOCK(wdog_clk, 0, CCM_CGR2, 24, NULL, NULL); DEFINE_CLOCK(max_clk, 0, CCM_CGR2, 26, NULL, NULL); DEFINE_CLOCK(admux_clk, 0, CCM_CGR2, 30, NULL, NULL); @@ -426,7 +439,10 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk) _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk) _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk) - _REGISTER_CLOCK(NULL, "usbotg", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usbotg_clk) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usbotg_clk) + _REGISTER_CLOCK("fsl-usb2-udc", "usb", usbotg_clk) _REGISTER_CLOCK("mxc_wdt.0", NULL, wdog_clk) _REGISTER_CLOCK(NULL, "max", max_clk) _REGISTER_CLOCK(NULL, "admux", admux_clk) @@ -456,7 +472,7 @@ int __init mx35_clocks_init() __raw_writel((3 << 26) | ll, CCM_BASE + CCM_CGR2); __raw_writel(0, CCM_BASE + CCM_CGR3); - mxc_timer_init(&gpt_clk); + mxc_timer_init(&gpt_clk, IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT); return 0; } diff --git a/arch/arm/mach-mx3/clock.c b/arch/arm/mach-mx3/clock.c index 8b14239724c9..06bd6180bfc3 100644 --- a/arch/arm/mach-mx3/clock.c +++ b/arch/arm/mach-mx3/clock.c @@ -29,6 +29,7 @@ #include <mach/clock.h> #include <mach/hardware.h> +#include <mach/mx31.h> #include <mach/common.h> #include "crm_regs.h" @@ -402,6 +403,11 @@ static unsigned long clk_ckih_get_rate(struct clk *clk) return ckih_rate; } +static unsigned long clk_ckil_get_rate(struct clk *clk) +{ + return CKIL_CLK_FREQ; +} + static struct clk ckih_clk = { .get_rate = clk_ckih_get_rate, }; @@ -508,6 +514,7 @@ DEFINE_CLOCK(usb_clk1, 0, NULL, 0, usb_get_rate, NULL, &usb_pll_clk) DEFINE_CLOCK(nfc_clk, 0, NULL, 0, nfc_get_rate, NULL, &ahb_clk); DEFINE_CLOCK(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_clk); DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk); +DEFINE_CLOCK(ckil_clk, 0, NULL, 0, clk_ckil_get_rate, NULL, NULL); #define _REGISTER_CLOCK(d, n, c) \ { \ @@ -518,9 +525,9 @@ DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk); static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "emi", emi_clk) - _REGISTER_CLOCK(NULL, "cspi", cspi1_clk) - _REGISTER_CLOCK(NULL, "cspi", cspi2_clk) - _REGISTER_CLOCK(NULL, "cspi", cspi3_clk) + _REGISTER_CLOCK("spi_imx.0", NULL, cspi1_clk) + _REGISTER_CLOCK("spi_imx.1", NULL, cspi2_clk) + _REGISTER_CLOCK("spi_imx.2", NULL, cspi3_clk) _REGISTER_CLOCK(NULL, "gpt", gpt_clk) _REGISTER_CLOCK(NULL, "pwm", pwm_clk) _REGISTER_CLOCK(NULL, "wdog", wdog_clk) @@ -531,6 +538,12 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("ipu-core", NULL, ipu_clk) _REGISTER_CLOCK("mx3_sdc_fb", NULL, ipu_clk) _REGISTER_CLOCK(NULL, "kpp", kpp_clk) + _REGISTER_CLOCK("mxc-ehci.0", "usb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_clk2) + _REGISTER_CLOCK("mxc-ehci.1", "usb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_clk2) + _REGISTER_CLOCK("mxc-ehci.2", "usb", usb_clk1) + _REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_clk2) _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk1) _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk2) _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk) @@ -559,6 +572,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(NULL, "iim", iim_clk) _REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk) _REGISTER_CLOCK(NULL, "mbx", mbx_clk) + _REGISTER_CLOCK("mxc_rtc", NULL, ckil_clk) }; int __init mx31_clocks_init(unsigned long fref) @@ -609,7 +623,7 @@ int __init mx31_clocks_init(unsigned long fref) __raw_writel(reg, MXC_CCM_PMCR1); } - mxc_timer_init(&ipg_clk); + mxc_timer_init(&ipg_clk, IO_ADDRESS(GPT1_BASE_ADDR), MXC_INT_GPT); return 0; } diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index 9e87e08fb121..8a577f367250 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -129,19 +129,17 @@ struct platform_device mxc_uart_device4 = { /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { - [0] = { + { .chip.label = "gpio-0", .base = IO_ADDRESS(GPIO1_BASE_ADDR), .irq = MXC_INT_GPIO1, .virtual_irq_start = MXC_GPIO_IRQ_START, - }, - [1] = { + }, { .chip.label = "gpio-1", .base = IO_ADDRESS(GPIO2_BASE_ADDR), .irq = MXC_INT_GPIO2, .virtual_irq_start = MXC_GPIO_IRQ_START + 32, - }, - [2] = { + }, { .chip.label = "gpio-2", .base = IO_ADDRESS(GPIO3_BASE_ADDR), .irq = MXC_INT_GPIO3, @@ -173,11 +171,11 @@ static struct resource mxc_nand_resources[] = { { .start = 0, /* runtime dependent */ .end = 0, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_MEM, }, { .start = MXC_INT_NANDFC, .end = MXC_INT_NANDFC, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ, }, }; @@ -193,8 +191,7 @@ static struct resource mxc_i2c0_resources[] = { .start = I2C_BASE_ADDR, .end = I2C_BASE_ADDR + SZ_4K - 1, .flags = IORESOURCE_MEM, - }, - { + }, { .start = MXC_INT_I2C, .end = MXC_INT_I2C, .flags = IORESOURCE_IRQ, @@ -213,8 +210,7 @@ static struct resource mxc_i2c1_resources[] = { .start = I2C2_BASE_ADDR, .end = I2C2_BASE_ADDR + SZ_4K - 1, .flags = IORESOURCE_MEM, - }, - { + }, { .start = MXC_INT_I2C2, .end = MXC_INT_I2C2, .flags = IORESOURCE_IRQ, @@ -233,8 +229,7 @@ static struct resource mxc_i2c2_resources[] = { .start = I2C3_BASE_ADDR, .end = I2C3_BASE_ADDR + SZ_4K - 1, .flags = IORESOURCE_MEM, - }, - { + }, { .start = MXC_INT_I2C3, .end = MXC_INT_I2C3, .flags = IORESOURCE_IRQ, @@ -371,8 +366,8 @@ struct platform_device mx3_camera = { static struct resource otg_resources[] = { { - .start = OTG_BASE_ADDR, - .end = OTG_BASE_ADDR + 0x1ff, + .start = MX31_OTG_BASE_ADDR, + .end = MX31_OTG_BASE_ADDR + 0x1ff, .flags = IORESOURCE_MEM, }, { .start = MXC_INT_USB3, @@ -395,16 +390,142 @@ struct platform_device mxc_otg_udc_device = { .num_resources = ARRAY_SIZE(otg_resources), }; +/* OTG host */ +struct platform_device mxc_otg_host = { + .name = "mxc-ehci", + .id = 0, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &otg_dmamask, + }, + .resource = otg_resources, + .num_resources = ARRAY_SIZE(otg_resources), +}; + +/* USB host 1 */ + +static u64 usbh1_dmamask = ~(u32)0; + +static struct resource mxc_usbh1_resources[] = { + { + .start = MX31_OTG_BASE_ADDR + 0x200, + .end = MX31_OTG_BASE_ADDR + 0x3ff, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_USB1, + .end = MXC_INT_USB1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_usbh1 = { + .name = "mxc-ehci", + .id = 1, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &usbh1_dmamask, + }, + .resource = mxc_usbh1_resources, + .num_resources = ARRAY_SIZE(mxc_usbh1_resources), +}; + +/* USB host 2 */ +static u64 usbh2_dmamask = ~(u32)0; + +static struct resource mxc_usbh2_resources[] = { + { + .start = MX31_OTG_BASE_ADDR + 0x400, + .end = MX31_OTG_BASE_ADDR + 0x5ff, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_USB2, + .end = MXC_INT_USB2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_usbh2 = { + .name = "mxc-ehci", + .id = 2, + .dev = { + .coherent_dma_mask = 0xffffffff, + .dma_mask = &usbh2_dmamask, + }, + .resource = mxc_usbh2_resources, + .num_resources = ARRAY_SIZE(mxc_usbh2_resources), +}; + +/* + * SPI master controller + * 3 channels + */ +static struct resource imx_spi_0_resources[] = { + { + .start = CSPI1_BASE_ADDR, + .end = CSPI1_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_CSPI1, + .end = MXC_INT_CSPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource imx_spi_1_resources[] = { + { + .start = CSPI2_BASE_ADDR, + .end = CSPI2_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_CSPI2, + .end = MXC_INT_CSPI2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource imx_spi_2_resources[] = { + { + .start = CSPI3_BASE_ADDR, + .end = CSPI3_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC_INT_CSPI3, + .end = MXC_INT_CSPI3, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device imx_spi_device0 = { + .name = "spi_imx", + .id = 0, + .num_resources = ARRAY_SIZE(imx_spi_0_resources), + .resource = imx_spi_0_resources, +}; + +struct platform_device imx_spi_device1 = { + .name = "spi_imx", + .id = 1, + .num_resources = ARRAY_SIZE(imx_spi_1_resources), + .resource = imx_spi_1_resources, +}; + +struct platform_device imx_spi_device2 = { + .name = "spi_imx", + .id = 2, + .num_resources = ARRAY_SIZE(imx_spi_2_resources), + .resource = imx_spi_2_resources, +}; + #ifdef CONFIG_ARCH_MX35 static struct resource mxc_fec_resources[] = { { .start = MXC_FEC_BASE_ADDR, .end = MXC_FEC_BASE_ADDR + 0xfff, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_MEM, }, { .start = MXC_INT_FEC, .end = MXC_INT_FEC, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ, }, }; @@ -426,6 +547,14 @@ static int mx3_devices_init(void) if (cpu_is_mx35()) { mxc_nand_resources[0].start = MX35_NFC_BASE_ADDR; mxc_nand_resources[0].end = MX35_NFC_BASE_ADDR + 0xfff; + otg_resources[0].start = MX35_OTG_BASE_ADDR; + otg_resources[0].end = MX35_OTG_BASE_ADDR + 0x1ff; + otg_resources[1].start = MXC_INT_USBOTG; + otg_resources[1].end = MXC_INT_USBOTG; + mxc_usbh1_resources[0].start = MX35_OTG_BASE_ADDR + 0x400; + mxc_usbh1_resources[0].end = MX35_OTG_BASE_ADDR + 0x5ff; + mxc_usbh1_resources[1].start = MXC_INT_USBHS; + mxc_usbh1_resources[1].end = MXC_INT_USBHS; } return 0; diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index ffd494ddd4ac..79f2be45d139 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -16,5 +16,11 @@ extern struct platform_device mxc_fec_device; extern struct platform_device mxcsdhc_device0; extern struct platform_device mxcsdhc_device1; extern struct platform_device mxc_otg_udc_device; +extern struct platform_device mxc_otg_host; +extern struct platform_device mxc_usbh1; +extern struct platform_device mxc_usbh2; extern struct platform_device mxc_rnga_device; +extern struct platform_device imx_spi_device0; +extern struct platform_device imx_spi_device1; +extern struct platform_device imx_spi_device2; diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c index 1f5fdd456cb9..ad5a1122d765 100644 --- a/arch/arm/mach-mx3/mm.c +++ b/arch/arm/mach-mx3/mm.c @@ -30,6 +30,7 @@ #include <mach/common.h> #include <mach/hardware.h> +#include <mach/iomux-v3.h> /*! * @file mm.c @@ -75,6 +76,7 @@ static struct map_desc mxc_io_desc[] __initdata = { void __init mx31_map_io(void) { mxc_set_cpu_type(MXC_CPU_MX31); + mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR)); iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); } @@ -82,10 +84,22 @@ void __init mx31_map_io(void) void __init mx35_map_io(void) { mxc_set_cpu_type(MXC_CPU_MX35); + mxc_iomux_v3_init(IO_ADDRESS(IOMUXC_BASE_ADDR)); + mxc_arch_reset_init(IO_ADDRESS(WDOG_BASE_ADDR)); iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); } +void __init mx31_init_irq(void) +{ + mxc_init_irq(IO_ADDRESS(AVIC_BASE_ADDR)); +} + +void __init mx35_init_irq(void) +{ + mx31_init_irq(); +} + #ifdef CONFIG_CACHE_L2X0 static int mxc_init_l2x0(void) { diff --git a/arch/arm/mach-mx3/mx31ads.c b/arch/arm/mach-mx3/mx31ads.c index 30e2767a78ae..0497c152be18 100644 --- a/arch/arm/mach-mx3/mx31ads.c +++ b/arch/arm/mach-mx3/mx31ads.c @@ -517,7 +517,7 @@ static void __init mx31ads_map_io(void) static void __init mx31ads_init_irq(void) { - mxc_init_irq(); + mx31_init_irq(); mx31ads_init_expio(); } diff --git a/arch/arm/mach-mx3/mx31lilly.c b/arch/arm/mach-mx3/mx31lilly.c index 6ab2f163cb95..423025150f6f 100644 --- a/arch/arm/mach-mx3/mx31lilly.c +++ b/arch/arm/mach-mx3/mx31lilly.c @@ -148,7 +148,7 @@ MACHINE_START(LILLY1131, "INCO startec LILLY-1131") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx31_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx31_init_irq, .init_machine = mx31lilly_board_init, .timer = &mx31lilly_timer, MACHINE_END diff --git a/arch/arm/mach-mx3/mx31lite.c b/arch/arm/mach-mx3/mx31lite.c index 86fe70fa3e13..a8d57decdfdb 100644 --- a/arch/arm/mach-mx3/mx31lite.c +++ b/arch/arm/mach-mx3/mx31lite.c @@ -71,12 +71,11 @@ static struct smsc911x_platform_config smsc911x_config = { }; static struct resource smsc911x_resources[] = { - [0] = { + { .start = CS4_BASE_ADDR, .end = CS4_BASE_ADDR + 0x100, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = IOMUX_TO_IRQ(MX31_PIN_SFS6), .end = IOMUX_TO_IRQ(MX31_PIN_SFS6), .flags = IORESOURCE_IRQ, @@ -162,7 +161,7 @@ MACHINE_START(MX31LITE, "LogicPD MX31 LITEKIT") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx31lite_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx31_init_irq, .init_machine = mxc_board_init, .timer = &mx31lite_timer, MACHINE_END diff --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c index 4704405165a1..b3e8f251ac79 100644 --- a/arch/arm/mach-mx3/mx31moboard-devboard.c +++ b/arch/arm/mach-mx3/mx31moboard-devboard.c @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/fsl_devices.h> #include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -40,18 +39,6 @@ static unsigned int devboard_pins[] = { MX31_PIN_PC_READY__SD2_DATA1, MX31_PIN_PC_WAIT_B__SD2_DATA0, MX31_PIN_PC_CD2_B__SD2_CLK, MX31_PIN_PC_CD1_B__SD2_CMD, MX31_PIN_ATA_DIOR__GPIO3_28, MX31_PIN_ATA_DIOW__GPIO3_29, - /* USB OTG */ - MX31_PIN_USBOTG_DATA0__USBOTG_DATA0, - MX31_PIN_USBOTG_DATA1__USBOTG_DATA1, - MX31_PIN_USBOTG_DATA2__USBOTG_DATA2, - MX31_PIN_USBOTG_DATA3__USBOTG_DATA3, - MX31_PIN_USBOTG_DATA4__USBOTG_DATA4, - MX31_PIN_USBOTG_DATA5__USBOTG_DATA5, - MX31_PIN_USBOTG_DATA6__USBOTG_DATA6, - MX31_PIN_USBOTG_DATA7__USBOTG_DATA7, - MX31_PIN_USBOTG_CLK__USBOTG_CLK, MX31_PIN_USBOTG_DIR__USBOTG_DIR, - MX31_PIN_USBOTG_NXT__USBOTG_NXT, MX31_PIN_USBOTG_STP__USBOTG_STP, - MX31_PIN_USB_OC__GPIO1_30, }; static struct imxuart_platform_data uart_pdata = { @@ -111,33 +98,6 @@ static struct imxmmc_platform_data sdhc2_pdata = { .exit = devboard_sdhc2_exit, }; -static struct fsl_usb2_platform_data usb_pdata = { - .operating_mode = FSL_USB2_DR_DEVICE, - .phy_mode = FSL_USB2_PHY_ULPI, -}; - -#define OTG_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST) -#define OTG_EN_B IOMUX_TO_GPIO(MX31_PIN_USB_OC) - -static void devboard_usbotg_init(void) -{ - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, OTG_PAD_CFG); - - gpio_request(OTG_EN_B, "usb-udc-en"); - gpio_direction_output(OTG_EN_B, 0); -} - /* * system init for baseboard usage. Will be called by mx31moboard init. */ @@ -151,7 +111,4 @@ void __init mx31moboard_devboard_init(void) mxc_register_device(&mxc_uart_device1, &uart_pdata); mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata); - - devboard_usbotg_init(); - mxc_register_device(&mxc_otg_udc_device, &usb_pdata); } diff --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c index 641c3d6153ae..3e2b73051b94 100644 --- a/arch/arm/mach-mx3/mx31moboard-marxbot.c +++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/fsl_devices.h> #include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -48,18 +47,8 @@ static unsigned int marxbot_pins[] = { MX31_PIN_CSI_PIXCLK__CSI_PIXCLK, MX31_PIN_CSI_VSYNC__CSI_VSYNC, MX31_PIN_GPIO3_0__GPIO3_0, MX31_PIN_GPIO3_1__GPIO3_1, MX31_PIN_TXD2__GPIO1_28, - /* USB OTG */ - MX31_PIN_USBOTG_DATA0__USBOTG_DATA0, - MX31_PIN_USBOTG_DATA1__USBOTG_DATA1, - MX31_PIN_USBOTG_DATA2__USBOTG_DATA2, - MX31_PIN_USBOTG_DATA3__USBOTG_DATA3, - MX31_PIN_USBOTG_DATA4__USBOTG_DATA4, - MX31_PIN_USBOTG_DATA5__USBOTG_DATA5, - MX31_PIN_USBOTG_DATA6__USBOTG_DATA6, - MX31_PIN_USBOTG_DATA7__USBOTG_DATA7, - MX31_PIN_USBOTG_CLK__USBOTG_CLK, MX31_PIN_USBOTG_DIR__USBOTG_DIR, - MX31_PIN_USBOTG_NXT__USBOTG_NXT, MX31_PIN_USBOTG_STP__USBOTG_STP, - MX31_PIN_USB_OC__GPIO1_30, + /* dsPIC resets */ + MX31_PIN_STXD5__GPIO1_21, MX31_PIN_SRXD5__GPIO1_22, }; #define SDHC2_CD IOMUX_TO_GPIO(MX31_PIN_ATA_DIOR) @@ -115,31 +104,20 @@ static struct imxmmc_platform_data sdhc2_pdata = { .exit = marxbot_sdhc2_exit, }; -static struct fsl_usb2_platform_data usb_pdata = { - .operating_mode = FSL_USB2_DR_DEVICE, - .phy_mode = FSL_USB2_PHY_ULPI, -}; - -#define OTG_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST) -#define OTG_EN_B IOMUX_TO_GPIO(MX31_PIN_USB_OC) +#define TRSLAT_RST_B IOMUX_TO_GPIO(MX31_PIN_STXD5) +#define DSPICS_RST_B IOMUX_TO_GPIO(MX31_PIN_SRXD5) -static void marxbot_usbotg_init(void) +static void dspics_resets_init(void) { - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, OTG_PAD_CFG); - mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, OTG_PAD_CFG); - - gpio_request(OTG_EN_B, "usb-udc-en"); - gpio_direction_output(OTG_EN_B, 0); + if (!gpio_request(TRSLAT_RST_B, "translator-rst")) { + gpio_direction_output(TRSLAT_RST_B, 1); + gpio_export(TRSLAT_RST_B, false); + } + + if (!gpio_request(DSPICS_RST_B, "dspics-rst")) { + gpio_direction_output(DSPICS_RST_B, 1); + gpio_export(DSPICS_RST_B, false); + } } /* @@ -152,8 +130,7 @@ void __init mx31moboard_marxbot_init(void) mxc_iomux_setup_multiple_pins(marxbot_pins, ARRAY_SIZE(marxbot_pins), "marxbot"); - mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata); + dspics_resets_init(); - marxbot_usbotg_init(); - mxc_register_device(&mxc_otg_udc_device, &usb_pdata); + mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata); } diff --git a/arch/arm/mach-mx3/mx31moboard.c b/arch/arm/mach-mx3/mx31moboard.c index a17f2e411609..d3c6bb26271f 100644 --- a/arch/arm/mach-mx3/mx31moboard.c +++ b/arch/arm/mach-mx3/mx31moboard.c @@ -16,9 +16,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/delay.h> +#include <linux/fsl_devices.h> #include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/leds.h> #include <linux/memory.h> #include <linux/mtd/physmap.h> #include <linux/mtd/partitions.h> @@ -36,6 +39,7 @@ #include <mach/iomux-mx3.h> #include <mach/i2c.h> #include <mach/mmc.h> +#include <mach/mx31.h> #include "devices.h" @@ -55,6 +59,26 @@ static unsigned int moboard_pins[] = { MX31_PIN_SD1_DATA1__SD1_DATA1, MX31_PIN_SD1_DATA0__SD1_DATA0, MX31_PIN_SD1_CLK__SD1_CLK, MX31_PIN_SD1_CMD__SD1_CMD, MX31_PIN_ATA_CS0__GPIO3_26, MX31_PIN_ATA_CS1__GPIO3_27, + /* USB reset */ + MX31_PIN_GPIO1_0__GPIO1_0, + /* USB OTG */ + MX31_PIN_USBOTG_DATA0__USBOTG_DATA0, + MX31_PIN_USBOTG_DATA1__USBOTG_DATA1, + MX31_PIN_USBOTG_DATA2__USBOTG_DATA2, + MX31_PIN_USBOTG_DATA3__USBOTG_DATA3, + MX31_PIN_USBOTG_DATA4__USBOTG_DATA4, + MX31_PIN_USBOTG_DATA5__USBOTG_DATA5, + MX31_PIN_USBOTG_DATA6__USBOTG_DATA6, + MX31_PIN_USBOTG_DATA7__USBOTG_DATA7, + MX31_PIN_USBOTG_CLK__USBOTG_CLK, MX31_PIN_USBOTG_DIR__USBOTG_DIR, + MX31_PIN_USBOTG_NXT__USBOTG_NXT, MX31_PIN_USBOTG_STP__USBOTG_STP, + MX31_PIN_USB_OC__GPIO1_30, + /* LEDs */ + MX31_PIN_SVEN0__GPIO2_0, MX31_PIN_STX0__GPIO2_1, + MX31_PIN_SRX0__GPIO2_2, MX31_PIN_SIMPD0__GPIO2_3, + /* SEL */ + MX31_PIN_DTR_DCE1__GPIO2_8, MX31_PIN_DSR_DCE1__GPIO2_9, + MX31_PIN_RI_DCE1__GPIO2_10, MX31_PIN_DCD_DCE1__GPIO2_11, }; static struct physmap_flash_data mx31moboard_flash_data = { @@ -142,8 +166,109 @@ static struct imxmmc_platform_data sdhc1_pdata = { .exit = moboard_sdhc1_exit, }; +/* + * this pin is dedicated for all mx31moboard systems, so we do it here + */ +#define USB_RESET_B IOMUX_TO_GPIO(MX31_PIN_GPIO1_0) + +static void usb_xcvr_reset(void) +{ + gpio_request(USB_RESET_B, "usb-reset"); + gpio_direction_output(USB_RESET_B, 0); + mdelay(1); + gpio_set_value(USB_RESET_B, 1); +} + +#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \ + PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU) + +#define OTG_EN_B IOMUX_TO_GPIO(MX31_PIN_USB_OC) + +static void moboard_usbotg_init(void) +{ + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG); + + gpio_request(OTG_EN_B, "usb-udc-en"); + gpio_direction_output(OTG_EN_B, 0); +} + +static struct fsl_usb2_platform_data usb_pdata = { + .operating_mode = FSL_USB2_DR_DEVICE, + .phy_mode = FSL_USB2_PHY_ULPI, +}; + +static struct gpio_led mx31moboard_leds[] = { + { + .name = "coreboard-led-0:red:running", + .default_trigger = "heartbeat", + .gpio = IOMUX_TO_GPIO(MX31_PIN_SVEN0), + }, { + .name = "coreboard-led-1:red", + .gpio = IOMUX_TO_GPIO(MX31_PIN_STX0), + }, { + .name = "coreboard-led-2:red", + .gpio = IOMUX_TO_GPIO(MX31_PIN_SRX0), + }, { + .name = "coreboard-led-3:red", + .gpio = IOMUX_TO_GPIO(MX31_PIN_SIMPD0), + }, +}; + +static struct gpio_led_platform_data mx31moboard_led_pdata = { + .num_leds = ARRAY_SIZE(mx31moboard_leds), + .leds = mx31moboard_leds, +}; + +static struct platform_device mx31moboard_leds_device = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &mx31moboard_led_pdata, + }, +}; + +#define SEL0 IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1) +#define SEL1 IOMUX_TO_GPIO(MX31_PIN_DSR_DCE1) +#define SEL2 IOMUX_TO_GPIO(MX31_PIN_RI_DCE1) +#define SEL3 IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1) + +static void mx31moboard_init_sel_gpios(void) +{ + if (!gpio_request(SEL0, "sel0")) { + gpio_direction_input(SEL0); + gpio_export(SEL0, true); + } + + if (!gpio_request(SEL1, "sel1")) { + gpio_direction_input(SEL1); + gpio_export(SEL1, true); + } + + if (!gpio_request(SEL2, "sel2")) { + gpio_direction_input(SEL2); + gpio_export(SEL2, true); + } + + if (!gpio_request(SEL3, "sel3")) { + gpio_direction_input(SEL3); + gpio_export(SEL3, true); + } +} + static struct platform_device *devices[] __initdata = { &mx31moboard_flash, + &mx31moboard_leds_device, }; static int mx31moboard_baseboard; @@ -162,11 +287,18 @@ static void __init mxc_board_init(void) mxc_register_device(&mxc_uart_device0, &uart_pdata); mxc_register_device(&mxc_uart_device4, &uart_pdata); + mx31moboard_init_sel_gpios(); + mxc_register_device(&mxc_i2c_device0, &moboard_i2c0_pdata); mxc_register_device(&mxc_i2c_device1, &moboard_i2c1_pdata); mxc_register_device(&mxcsdhc_device0, &sdhc1_pdata); + usb_xcvr_reset(); + + moboard_usbotg_init(); + mxc_register_device(&mxc_otg_udc_device, &usb_pdata); + switch (mx31moboard_baseboard) { case MX31NOBOARD: break; @@ -197,7 +329,7 @@ MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx31_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx31_init_irq, .init_machine = mxc_board_init, .timer = &mx31moboard_timer, MACHINE_END diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c index c19838d2e369..0f7a2f06bc2d 100644 --- a/arch/arm/mach-mx3/mx31pdk.c +++ b/arch/arm/mach-mx3/mx31pdk.c @@ -265,7 +265,7 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx31pdk_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx31_init_irq, .init_machine = mxc_board_init, .timer = &mx31pdk_timer, MACHINE_END diff --git a/arch/arm/mach-mx3/mx35pdk.c b/arch/arm/mach-mx3/mx35pdk.c index 6d15374414b9..6ff186e46ceb 100644 --- a/arch/arm/mach-mx3/mx35pdk.c +++ b/arch/arm/mach-mx3/mx35pdk.c @@ -98,7 +98,7 @@ MACHINE_START(MX35_3DS, "Freescale MX35PDK") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx35_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx35_init_irq, .init_machine = mxc_board_init, .timer = &mx35pdk_timer, MACHINE_END diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index c6f61a1f06c8..6cbaabedf386 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -18,7 +18,7 @@ #include <linux/types.h> #include <linux/init.h> - +#include <linux/dma-mapping.h> #include <linux/platform_device.h> #include <linux/mtd/physmap.h> #include <linux/mtd/plat-ram.h> @@ -32,30 +32,69 @@ #include <linux/spi/spi.h> #include <linux/irq.h> #include <linux/fsl_devices.h> +#include <linux/can/platform/sja1000.h> + +#include <media/soc_camera.h> -#include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/mach/time.h> #include <asm/mach/map.h> +#include <mach/board-pcm037.h> #include <mach/common.h> +#include <mach/hardware.h> +#include <mach/i2c.h> #include <mach/imx-uart.h> #include <mach/iomux-mx3.h> #include <mach/ipu.h> -#include <mach/board-pcm037.h> +#include <mach/mmc.h> +#include <mach/mx3_camera.h> #include <mach/mx3fb.h> #include <mach/mxc_nand.h> -#include <mach/mmc.h> -#ifdef CONFIG_I2C_IMX -#include <mach/i2c.h> -#endif #include "devices.h" +#include "pcm037.h" + +static enum pcm037_board_variant pcm037_instance = PCM037_PCM970; + +static int __init pcm037_variant_setup(char *str) +{ + if (!strcmp("eet", str)) + pcm037_instance = PCM037_EET; + else if (strcmp("pcm970", str)) + pr_warning("Unknown pcm037 baseboard variant %s\n", str); + + return 1; +} + +/* Supported values: "pcm970" (default) and "eet" */ +__setup("pcm037_variant=", pcm037_variant_setup); + +enum pcm037_board_variant pcm037_variant(void) +{ + return pcm037_instance; +} + +/* UART1 with RTS/CTS handshake signals */ +static unsigned int pcm037_uart1_handshake_pins[] = { + MX31_PIN_CTS1__CTS1, + MX31_PIN_RTS1__RTS1, + MX31_PIN_TXD1__TXD1, + MX31_PIN_RXD1__RXD1, +}; + +/* UART1 without RTS/CTS handshake signals */ +static unsigned int pcm037_uart1_pins[] = { + MX31_PIN_TXD1__TXD1, + MX31_PIN_RXD1__RXD1, +}; static unsigned int pcm037_pins[] = { /* I2C */ MX31_PIN_CSPI2_MOSI__SCL, MX31_PIN_CSPI2_MISO__SDA, + MX31_PIN_CSPI2_SS2__I2C3_SDA, + MX31_PIN_CSPI2_SCLK__I2C3_SCL, /* SDHC1 */ MX31_PIN_SD1_DATA3__SD1_DATA3, MX31_PIN_SD1_DATA2__SD1_DATA2, @@ -73,11 +112,6 @@ static unsigned int pcm037_pins[] = { MX31_PIN_CSPI1_SS0__SS0, MX31_PIN_CSPI1_SS1__SS1, MX31_PIN_CSPI1_SS2__SS2, - /* UART1 */ - MX31_PIN_CTS1__CTS1, - MX31_PIN_RTS1__RTS1, - MX31_PIN_TXD1__TXD1, - MX31_PIN_RXD1__RXD1, /* UART2 */ MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2, @@ -120,6 +154,24 @@ static unsigned int pcm037_pins[] = { MX31_PIN_D3_SPL__D3_SPL, MX31_PIN_D3_CLS__D3_CLS, MX31_PIN_LCS0__GPI03_23, + /* CSI */ + IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO), + MX31_PIN_CSI_D6__CSI_D6, + MX31_PIN_CSI_D7__CSI_D7, + MX31_PIN_CSI_D8__CSI_D8, + MX31_PIN_CSI_D9__CSI_D9, + MX31_PIN_CSI_D10__CSI_D10, + MX31_PIN_CSI_D11__CSI_D11, + MX31_PIN_CSI_D12__CSI_D12, + MX31_PIN_CSI_D13__CSI_D13, + MX31_PIN_CSI_D14__CSI_D14, + MX31_PIN_CSI_D15__CSI_D15, + MX31_PIN_CSI_HSYNC__CSI_HSYNC, + MX31_PIN_CSI_MCLK__CSI_MCLK, + MX31_PIN_CSI_PIXCLK__CSI_PIXCLK, + MX31_PIN_CSI_VSYNC__CSI_VSYNC, + /* GPIO */ + IOMUX_MODE(MX31_PIN_ATA_DMACK, IOMUX_CONFIG_GPIO), }; static struct physmap_flash_data pcm037_flash_data = { @@ -195,12 +247,11 @@ static struct imxuart_platform_data uart_pdata = { }; static struct resource smsc911x_resources[] = { - [0] = { + { .start = CS1_BASE_ADDR + 0x300, .end = CS1_BASE_ADDR + 0x300 + SZ_64K - 1, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), .end = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, @@ -250,27 +301,57 @@ static struct mxc_nand_platform_data pcm037_nand_board_info = { .hw_ecc = 1, }; -#ifdef CONFIG_I2C_IMX static struct imxi2c_platform_data pcm037_i2c_1_data = { .bitrate = 100000, }; +static struct imxi2c_platform_data pcm037_i2c_2_data = { + .bitrate = 20000, +}; + static struct at24_platform_data board_eeprom = { .byte_len = 4096, .page_size = 32, .flags = AT24_FLAG_ADDR16, }; +static int pcm037_camera_power(struct device *dev, int on) +{ + /* disable or enable the camera in X7 or X8 PCM970 connector */ + gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), !on); + return 0; +} + +static struct i2c_board_info pcm037_i2c_2_devices[] = { + { + I2C_BOARD_INFO("mt9t031", 0x5d), + }, +}; + +static struct soc_camera_link iclink = { + .bus_id = 0, /* Must match with the camera ID */ + .power = pcm037_camera_power, + .board_info = &pcm037_i2c_2_devices[0], + .i2c_adapter_id = 2, + .module_name = "mt9t031", +}; + static struct i2c_board_info pcm037_i2c_devices[] = { - { + { I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ .platform_data = &board_eeprom, }, { - I2C_BOARD_INFO("rtc-pcf8563", 0x51), - .type = "pcf8563", + I2C_BOARD_INFO("pcf8563", 0x51), } }; -#endif + +static struct platform_device pcm037_camera = { + .name = "soc-camera-pdrv", + .id = 0, + .dev = { + .platform_data = &iclink, + }, +}; /* Not connected by default */ #ifdef PCM970_SDHC_RW_SWITCH @@ -334,9 +415,41 @@ static struct imxmmc_platform_data sdhc_pdata = { .exit = pcm970_sdhc1_exit, }; +struct mx3_camera_pdata camera_pdata = { + .dma_dev = &mx3_ipu.dev, + .flags = MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10, + .mclk_10khz = 2000, +}; + +static int __init pcm037_camera_alloc_dma(const size_t buf_size) +{ + dma_addr_t dma_handle; + void *buf; + int dma; + + if (buf_size < 2 * 1024 * 1024) + return -EINVAL; + + buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL); + if (!buf) { + pr_err("%s: cannot allocate camera buffer-memory\n", __func__); + return -ENOMEM; + } + + memset(buf, 0, buf_size); + + dma = dma_declare_coherent_memory(&mx3_camera.dev, + dma_handle, dma_handle, buf_size, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE); + + /* The way we call dma_declare_coherent_memory only a malloc can fail */ + return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM; +} + static struct platform_device *devices[] __initdata = { &pcm037_flash, &pcm037_sram_device, + &pcm037_camera, }; static struct ipu_platform_data mx3_ipu_data = { @@ -377,6 +490,22 @@ static const struct fb_videomode fb_modedb[] = { .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH, .vmode = FB_VMODE_NONINTERLACED, .flag = 0, + }, { + /* 240x320 @ 60 Hz */ + .name = "CMEL-OLED", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 185925, + .left_margin = 9, + .right_margin = 16, + .upper_margin = 7, + .lower_margin = 9, + .hsync_len = 1, + .vsync_len = 1, + .sync = FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT, + .vmode = FB_VMODE_NONINTERLACED, + .flag = 0, }, }; @@ -387,6 +516,33 @@ static struct mx3fb_platform_data mx3fb_pdata = { .num_modes = ARRAY_SIZE(fb_modedb), }; +static struct resource pcm970_sja1000_resources[] = { + { + .start = CS5_BASE_ADDR, + .end = CS5_BASE_ADDR + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)), + .end = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, + }, +}; + +struct sja1000_platform_data pcm970_sja1000_platform_data = { + .clock = 16000000 / 2, + .ocr = 0x40 | 0x18, + .cdr = 0x40, +}; + +static struct platform_device pcm970_sja1000 = { + .name = "sja1000_platform", + .dev = { + .platform_data = &pcm970_sja1000_platform_data, + }, + .resource = pcm970_sja1000_resources, + .num_resources = ARRAY_SIZE(pcm970_sja1000_resources), +}; + /* * Board specific initialization. */ @@ -397,6 +553,14 @@ static void __init mxc_board_init(void) mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins), "pcm037"); + if (pcm037_variant() == PCM037_EET) + mxc_iomux_setup_multiple_pins(pcm037_uart1_pins, + ARRAY_SIZE(pcm037_uart1_pins), "pcm037_uart1"); + else + mxc_iomux_setup_multiple_pins(pcm037_uart1_handshake_pins, + ARRAY_SIZE(pcm037_uart1_handshake_pins), + "pcm037_uart1"); + platform_add_devices(devices, ARRAY_SIZE(devices)); mxc_register_device(&mxc_uart_device0, &uart_pdata); @@ -415,18 +579,32 @@ static void __init mxc_board_init(void) } -#ifdef CONFIG_I2C_IMX + /* I2C adapters and devices */ i2c_register_board_info(1, pcm037_i2c_devices, ARRAY_SIZE(pcm037_i2c_devices)); mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data); -#endif + mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data); + mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info); mxc_register_device(&mxcsdhc_device0, &sdhc_pdata); mxc_register_device(&mx3_ipu, &mx3_ipu_data); mxc_register_device(&mx3_fb, &mx3fb_pdata); if (!gpio_usbotg_hs_activate()) mxc_register_device(&mxc_otg_udc_device, &usb_pdata); + + /* CSI */ + /* Camera power: default - off */ + ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), "mt9t031-power"); + if (!ret) + gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1); + else + iclink.power = NULL; + + if (!pcm037_camera_alloc_dma(4 * 1024 * 1024)) + mxc_register_device(&mx3_camera, &camera_pdata); + + platform_device_register(&pcm970_sja1000); } static void __init pcm037_timer_init(void) @@ -444,8 +622,7 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx31_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx31_init_irq, .init_machine = mxc_board_init, .timer = &pcm037_timer, MACHINE_END - diff --git a/arch/arm/mach-mx3/pcm037.h b/arch/arm/mach-mx3/pcm037.h new file mode 100644 index 000000000000..d6929721a5fd --- /dev/null +++ b/arch/arm/mach-mx3/pcm037.h @@ -0,0 +1,11 @@ +#ifndef __PCM037_H__ +#define __PCM037_H__ + +enum pcm037_board_variant { + PCM037_PCM970, + PCM037_EET, +}; + +extern enum pcm037_board_variant pcm037_variant(void); + +#endif diff --git a/arch/arm/mach-mx3/pcm037_eet.c b/arch/arm/mach-mx3/pcm037_eet.c new file mode 100644 index 000000000000..fe52fb1bb8b7 --- /dev/null +++ b/arch/arm/mach-mx3/pcm037_eet.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2009 + * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/gpio.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> + +#include <mach/common.h> +#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE) +#include <mach/spi.h> +#endif +#include <mach/iomux-mx3.h> + +#include <asm/mach-types.h> + +#include "pcm037.h" +#include "devices.h" + +static unsigned int pcm037_eet_pins[] = { + /* SPI #1 */ + MX31_PIN_CSPI1_MISO__MISO, + MX31_PIN_CSPI1_MOSI__MOSI, + MX31_PIN_CSPI1_SCLK__SCLK, + MX31_PIN_CSPI1_SPI_RDY__SPI_RDY, + MX31_PIN_CSPI1_SS0__SS0, + MX31_PIN_CSPI1_SS1__SS1, + MX31_PIN_CSPI1_SS2__SS2, + + /* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */ + IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_GPIO), + /* GPIO keys */ + IOMUX_MODE(MX31_PIN_GPIO1_0, IOMUX_CONFIG_GPIO), /* 0 */ + IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO), /* 1 */ + IOMUX_MODE(MX31_PIN_GPIO1_2, IOMUX_CONFIG_GPIO), /* 2 */ + IOMUX_MODE(MX31_PIN_GPIO1_3, IOMUX_CONFIG_GPIO), /* 3 */ + IOMUX_MODE(MX31_PIN_SVEN0, IOMUX_CONFIG_GPIO), /* 32 */ + IOMUX_MODE(MX31_PIN_STX0, IOMUX_CONFIG_GPIO), /* 33 */ + IOMUX_MODE(MX31_PIN_SRX0, IOMUX_CONFIG_GPIO), /* 34 */ + IOMUX_MODE(MX31_PIN_SIMPD0, IOMUX_CONFIG_GPIO), /* 35 */ + IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_GPIO), /* 38 */ + IOMUX_MODE(MX31_PIN_CTS1, IOMUX_CONFIG_GPIO), /* 39 */ + IOMUX_MODE(MX31_PIN_KEY_ROW4, IOMUX_CONFIG_GPIO), /* 50 */ + IOMUX_MODE(MX31_PIN_KEY_ROW5, IOMUX_CONFIG_GPIO), /* 51 */ + IOMUX_MODE(MX31_PIN_KEY_ROW6, IOMUX_CONFIG_GPIO), /* 52 */ + IOMUX_MODE(MX31_PIN_KEY_ROW7, IOMUX_CONFIG_GPIO), /* 53 */ + + /* LEDs */ + IOMUX_MODE(MX31_PIN_DTR_DTE1, IOMUX_CONFIG_GPIO), /* 44 */ + IOMUX_MODE(MX31_PIN_DSR_DTE1, IOMUX_CONFIG_GPIO), /* 45 */ + IOMUX_MODE(MX31_PIN_KEY_COL5, IOMUX_CONFIG_GPIO), /* 55 */ + IOMUX_MODE(MX31_PIN_KEY_COL6, IOMUX_CONFIG_GPIO), /* 56 */ +}; + +/* SPI */ +static struct spi_board_info pcm037_spi_dev[] = { + { + .modalias = "dac124s085", + .max_speed_hz = 400000, + .bus_num = 0, + .chip_select = 0, /* Index in pcm037_spi1_cs[] */ + .mode = SPI_CPHA, + }, +}; + +/* Platform Data for MXC CSPI */ +#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE) +static int pcm037_spi1_cs[] = {MXC_SPI_CS(1), IOMUX_TO_GPIO(MX31_PIN_KEY_COL7)}; + +struct spi_imx_master pcm037_spi1_master = { + .chipselect = pcm037_spi1_cs, + .num_chipselect = ARRAY_SIZE(pcm037_spi1_cs), +}; +#endif + +/* GPIO-keys input device */ +static struct gpio_keys_button pcm037_gpio_keys[] = { + { + .type = EV_KEY, + .code = KEY_L, + .gpio = 0, + .desc = "Wheel Manual", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_A, + .gpio = 1, + .desc = "Wheel AF", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_V, + .gpio = 2, + .desc = "Wheel View", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_M, + .gpio = 3, + .desc = "Wheel Menu", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_UP, + .gpio = 32, + .desc = "Nav Pad Up", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_RIGHT, + .gpio = 33, + .desc = "Nav Pad Right", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_DOWN, + .gpio = 34, + .desc = "Nav Pad Down", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_LEFT, + .gpio = 35, + .desc = "Nav Pad Left", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_ENTER, + .gpio = 38, + .desc = "Nav Pad Ok", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = KEY_O, + .gpio = 39, + .desc = "Wheel Off", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = BTN_FORWARD, + .gpio = 50, + .desc = "Focus Forward", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = BTN_BACK, + .gpio = 51, + .desc = "Focus Backward", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = BTN_MIDDLE, + .gpio = 52, + .desc = "Release Half", + .wakeup = 0, + }, { + .type = EV_KEY, + .code = BTN_EXTRA, + .gpio = 53, + .desc = "Release Full", + .wakeup = 0, + }, +}; + +static struct gpio_keys_platform_data pcm037_gpio_keys_platform_data = { + .buttons = pcm037_gpio_keys, + .nbuttons = ARRAY_SIZE(pcm037_gpio_keys), + .rep = 0, /* No auto-repeat */ +}; + +static struct platform_device pcm037_gpio_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &pcm037_gpio_keys_platform_data, + }, +}; + +static int eet_init_devices(void) +{ + if (!machine_is_pcm037() || pcm037_variant() != PCM037_EET) + return 0; + + mxc_iomux_setup_multiple_pins(pcm037_eet_pins, + ARRAY_SIZE(pcm037_eet_pins), "pcm037_eet"); + + /* SPI */ + spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev)); +#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE) + mxc_register_device(&mxc_spi_device0, &pcm037_spi1_master); +#endif + + platform_device_register(&pcm037_gpio_keys_device); + + return 0; +} + +late_initcall(eet_init_devices); diff --git a/arch/arm/mach-mx3/pcm043.c b/arch/arm/mach-mx3/pcm043.c index 8d27c324abf2..e18a224671fa 100644 --- a/arch/arm/mach-mx3/pcm043.c +++ b/arch/arm/mach-mx3/pcm043.c @@ -133,8 +133,7 @@ static struct i2c_board_info pcm043_i2c_devices[] = { I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ .platform_data = &board_eeprom, }, { - I2C_BOARD_INFO("rtc-pcf8563", 0x51), - .type = "pcf8563", + I2C_BOARD_INFO("pcf8563", 0x51), } }; #endif @@ -203,7 +202,8 @@ static struct pad_desc pcm043_pads[] = { MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC, MX35_PAD_D3_REV__IPU_DISPB_D3_REV, MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS, - MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL + /* gpio */ + MX35_PAD_ATA_CS0__GPIO2_6, }; /* @@ -245,7 +245,7 @@ MACHINE_START(PCM043, "Phytec Phycore pcm043") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx35_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx35_init_irq, .init_machine = mxc_board_init, .timer = &pcm043_timer, MACHINE_END diff --git a/arch/arm/mach-mx3/qong.c b/arch/arm/mach-mx3/qong.c index 82b31c4ab11f..044511f1b9a9 100644 --- a/arch/arm/mach-mx3/qong.c +++ b/arch/arm/mach-mx3/qong.c @@ -81,13 +81,12 @@ static inline void mxc_init_imx_uart(void) } static struct resource dnet_resources[] = { - [0] = { + { .name = "dnet-memory", .start = QONG_DNET_BASEADDR, .end = QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1, .flags = IORESOURCE_MEM, - }, - [1] = { + }, { .start = QONG_FPGA_IRQ, .end = QONG_FPGA_IRQ, .flags = IORESOURCE_IRQ, @@ -280,7 +279,7 @@ MACHINE_START(QONG, "Dave/DENX QongEVB-LITE") .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, .boot_params = PHYS_OFFSET + 0x100, .map_io = mx31_map_io, - .init_irq = mxc_init_irq, + .init_irq = mx31_init_irq, .init_machine = mxc_board_init, .timer = &qong_timer, MACHINE_END diff --git a/arch/arm/mach-mxc91231/Kconfig b/arch/arm/mach-mxc91231/Kconfig new file mode 100644 index 000000000000..8e5fa38ebb67 --- /dev/null +++ b/arch/arm/mach-mxc91231/Kconfig @@ -0,0 +1,11 @@ +if ARCH_MXC91231 + +comment "MXC91231 platforms:" + +config MACH_MAGX_ZN5 + bool "Support Motorola Zn5 GSM phone" + default n + help + Include support for Motorola Zn5 GSM phone. + +endif diff --git a/arch/arm/mach-mxc91231/Makefile b/arch/arm/mach-mxc91231/Makefile new file mode 100644 index 000000000000..011d5e197125 --- /dev/null +++ b/arch/arm/mach-mxc91231/Makefile @@ -0,0 +1,2 @@ +obj-y := mm.o clock.o devices.o system.o iomux.o +obj-$(CONFIG_MACH_MAGX_ZN5) += magx-zn5.o diff --git a/arch/arm/mach-mxc91231/Makefile.boot b/arch/arm/mach-mxc91231/Makefile.boot new file mode 100644 index 000000000000..9939a19d99a1 --- /dev/null +++ b/arch/arm/mach-mxc91231/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x90008000 +params_phys-y := 0x90000100 +initrd_phys-y := 0x90800000 diff --git a/arch/arm/mach-mxc91231/clock.c b/arch/arm/mach-mxc91231/clock.c new file mode 100644 index 000000000000..ecfa37fef8ad --- /dev/null +++ b/arch/arm/mach-mxc91231/clock.c @@ -0,0 +1,642 @@ +#include <linux/clk.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> + +#include <mach/clock.h> +#include <mach/hardware.h> +#include <mach/common.h> + +#include <asm/clkdev.h> +#include <asm/bug.h> +#include <asm/div64.h> + +#include "crm_regs.h" + +#define CRM_SMALL_DIVIDER(base, name) \ + crm_small_divider(base, \ + base ## _ ## name ## _OFFSET, \ + base ## _ ## name ## _MASK) +#define CRM_1DIVIDER(base, name) \ + crm_divider(base, \ + base ## _ ## name ## _OFFSET, \ + base ## _ ## name ## _MASK, 1) +#define CRM_16DIVIDER(base, name) \ + crm_divider(base, \ + base ## _ ## name ## _OFFSET, \ + base ## _ ## name ## _MASK, 16) + +static u32 crm_small_divider(void __iomem *reg, u8 offset, u32 mask) +{ + static const u32 crm_small_dividers[] = { + 2, 3, 4, 5, 6, 8, 10, 12 + }; + u8 idx; + + idx = (__raw_readl(reg) & mask) >> offset; + if (idx > 7) + return 1; + + return crm_small_dividers[idx]; +} + +static u32 crm_divider(void __iomem *reg, u8 offset, u32 mask, u32 z) +{ + u32 div; + div = (__raw_readl(reg) & mask) >> offset; + return div ? div : z; +} + +static int _clk_1bit_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 1 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void _clk_1bit_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(1 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static int _clk_3bit_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= 0x7 << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + + return 0; +} + +static void _clk_3bit_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(0x7 << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); +} + +static unsigned long ckih_rate; + +static unsigned long clk_ckih_get_rate(struct clk *clk) +{ + return ckih_rate; +} + +static struct clk ckih_clk = { + .get_rate = clk_ckih_get_rate, +}; + +static unsigned long clk_ckih_x2_get_rate(struct clk *clk) +{ + return 2 * clk_get_rate(clk->parent); +} + +static struct clk ckih_x2_clk = { + .parent = &ckih_clk, + .get_rate = clk_ckih_x2_get_rate, +}; + +static unsigned long clk_ckil_get_rate(struct clk *clk) +{ + return CKIL_CLK_FREQ; +} + +static struct clk ckil_clk = { + .get_rate = clk_ckil_get_rate, +}; + +/* plls stuff */ +static struct clk mcu_pll_clk; +static struct clk dsp_pll_clk; +static struct clk usb_pll_clk; + +static struct clk *pll_clk(u8 sel) +{ + switch (sel) { + case 0: + return &mcu_pll_clk; + case 1: + return &dsp_pll_clk; + case 2: + return &usb_pll_clk; + } + BUG(); +} + +static void __iomem *pll_base(struct clk *clk) +{ + if (clk == &mcu_pll_clk) + return MXC_PLL0_BASE; + else if (clk == &dsp_pll_clk) + return MXC_PLL1_BASE; + else if (clk == &usb_pll_clk) + return MXC_PLL2_BASE; + BUG(); +} + +static unsigned long clk_pll_get_rate(struct clk *clk) +{ + const void __iomem *pllbase; + unsigned long dp_op, dp_mfd, dp_mfn, pll_hfsm, ref_clk, mfi; + long mfn, mfn_abs, mfd, pdf; + s64 temp; + pllbase = pll_base(clk); + + pll_hfsm = __raw_readl(pllbase + MXC_PLL_DP_CTL) & MXC_PLL_DP_CTL_HFSM; + if (pll_hfsm == 0) { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN); + } else { + dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP); + dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD); + dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN); + } + + pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK; + mfi = (dp_op >> MXC_PLL_DP_OP_MFI_OFFSET) & MXC_PLL_DP_OP_PDF_MASK; + mfi = (mfi <= 5) ? 5 : mfi; + mfd = dp_mfd & MXC_PLL_DP_MFD_MASK; + mfn = dp_mfn & MXC_PLL_DP_MFN_MASK; + mfn = (mfn <= 0x4000000) ? mfn : (mfn - 0x10000000); + + if (mfn < 0) + mfn_abs = -mfn; + else + mfn_abs = mfn; + +/* XXX: actually this asumes that ckih is fed to pll, but spec says + * that ckih_x2 is also possible. need to check this out. + */ + ref_clk = clk_get_rate(&ckih_clk); + + ref_clk *= 2; + ref_clk /= pdf + 1; + + temp = (u64) ref_clk * mfn_abs; + do_div(temp, mfd); + if (mfn < 0) + temp = -temp; + temp += ref_clk * mfi; + + return temp; +} + +static int clk_pll_enable(struct clk *clk) +{ + void __iomem *ctl; + u32 reg; + + ctl = pll_base(clk); + reg = __raw_readl(ctl); + reg |= (MXC_PLL_DP_CTL_RST | MXC_PLL_DP_CTL_UPEN); + __raw_writel(reg, ctl); + do { + reg = __raw_readl(ctl); + } while ((reg & MXC_PLL_DP_CTL_LRF) != MXC_PLL_DP_CTL_LRF); + return 0; +} + +static void clk_pll_disable(struct clk *clk) +{ + void __iomem *ctl; + u32 reg; + + ctl = pll_base(clk); + reg = __raw_readl(ctl); + reg &= ~(MXC_PLL_DP_CTL_RST | MXC_PLL_DP_CTL_UPEN); + __raw_writel(reg, ctl); +} + +static struct clk mcu_pll_clk = { + .parent = &ckih_clk, + .get_rate = clk_pll_get_rate, + .enable = clk_pll_enable, + .disable = clk_pll_disable, +}; + +static struct clk dsp_pll_clk = { + .parent = &ckih_clk, + .get_rate = clk_pll_get_rate, + .enable = clk_pll_enable, + .disable = clk_pll_disable, +}; + +static struct clk usb_pll_clk = { + .parent = &ckih_clk, + .get_rate = clk_pll_get_rate, + .enable = clk_pll_enable, + .disable = clk_pll_disable, +}; +/* plls stuff end */ + +/* ap_ref_clk stuff */ +static struct clk ap_ref_clk; + +static unsigned long clk_ap_ref_get_rate(struct clk *clk) +{ + u32 ascsr, acsr; + u8 ap_pat_ref_div_2, ap_isel, acs, ads; + + ascsr = __raw_readl(MXC_CRMAP_ASCSR); + acsr = __raw_readl(MXC_CRMAP_ACSR); + + /* 0 for ckih, 1 for ckih*2 */ + ap_isel = ascsr & MXC_CRMAP_ASCSR_APISEL; + /* reg divider */ + ap_pat_ref_div_2 = (ascsr >> MXC_CRMAP_ASCSR_AP_PATDIV2_OFFSET) & 0x1; + /* undocumented, 1 for disabling divider */ + ads = (acsr >> MXC_CRMAP_ACSR_ADS_OFFSET) & 0x1; + /* 0 for pat_ref, 1 for divider out */ + acs = acsr & MXC_CRMAP_ACSR_ACS; + + if (acs & !ads) + /* use divided clock */ + return clk_get_rate(clk->parent) / (ap_pat_ref_div_2 ? 2 : 1); + + return clk_get_rate(clk->parent) * (ap_isel ? 2 : 1); +} + +static struct clk ap_ref_clk = { + .parent = &ckih_clk, + .get_rate = clk_ap_ref_get_rate, +}; +/* ap_ref_clk stuff end */ + +/* ap_pre_dfs_clk stuff */ +static struct clk ap_pre_dfs_clk; + +static unsigned long clk_ap_pre_dfs_get_rate(struct clk *clk) +{ + u32 acsr, ascsr; + + acsr = __raw_readl(MXC_CRMAP_ACSR); + ascsr = __raw_readl(MXC_CRMAP_ASCSR); + + if (acsr & MXC_CRMAP_ACSR_ACS) { + u8 sel; + sel = (ascsr & MXC_CRMAP_ASCSR_APSEL_MASK) >> + MXC_CRMAP_ASCSR_APSEL_OFFSET; + return clk_get_rate(pll_clk(sel)) / + CRM_SMALL_DIVIDER(MXC_CRMAP_ACDR, ARMDIV); + } + return clk_get_rate(&ap_ref_clk); +} + +static struct clk ap_pre_dfs_clk = { + .get_rate = clk_ap_pre_dfs_get_rate, +}; +/* ap_pre_dfs_clk stuff end */ + +/* usb_clk stuff */ +static struct clk usb_clk; + +static struct clk *clk_usb_parent(struct clk *clk) +{ + u32 acsr, ascsr; + + acsr = __raw_readl(MXC_CRMAP_ACSR); + ascsr = __raw_readl(MXC_CRMAP_ASCSR); + + if (acsr & MXC_CRMAP_ACSR_ACS) { + u8 sel; + sel = (ascsr & MXC_CRMAP_ASCSR_USBSEL_MASK) >> + MXC_CRMAP_ASCSR_USBSEL_OFFSET; + return pll_clk(sel); + } + return &ap_ref_clk; +} + +static unsigned long clk_usb_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / + CRM_SMALL_DIVIDER(MXC_CRMAP_ACDER2, USBDIV); +} + +static struct clk usb_clk = { + .enable_reg = MXC_CRMAP_ACDER2, + .enable_shift = MXC_CRMAP_ACDER2_USBEN_OFFSET, + .get_rate = clk_usb_get_rate, + .enable = _clk_1bit_enable, + .disable = _clk_1bit_disable, +}; +/* usb_clk stuff end */ + +static unsigned long clk_ipg_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / CRM_16DIVIDER(MXC_CRMAP_ACDR, IPDIV); +} + +static unsigned long clk_ahb_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / + CRM_16DIVIDER(MXC_CRMAP_ACDR, AHBDIV); +} + +static struct clk ipg_clk = { + .parent = &ap_pre_dfs_clk, + .get_rate = clk_ipg_get_rate, +}; + +static struct clk ahb_clk = { + .parent = &ap_pre_dfs_clk, + .get_rate = clk_ahb_get_rate, +}; + +/* perclk_clk stuff */ +static struct clk perclk_clk; + +static unsigned long clk_perclk_get_rate(struct clk *clk) +{ + u32 acder2; + + acder2 = __raw_readl(MXC_CRMAP_ACDER2); + if (acder2 & MXC_CRMAP_ACDER2_BAUD_ISEL_MASK) + return 2 * clk_get_rate(clk->parent); + + return clk_get_rate(clk->parent); +} + +static struct clk perclk_clk = { + .parent = &ckih_clk, + .get_rate = clk_perclk_get_rate, +}; +/* perclk_clk stuff end */ + +/* uart_clk stuff */ +static struct clk uart_clk[]; + +static unsigned long clk_uart_get_rate(struct clk *clk) +{ + u32 div; + + switch (clk->id) { + case 0: + case 1: + div = CRM_SMALL_DIVIDER(MXC_CRMAP_ACDER2, BAUDDIV); + break; + case 2: + div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRA, UART3DIV); + break; + default: + BUG(); + } + return clk_get_rate(clk->parent) / div; +} + +static struct clk uart_clk[] = { + { + .id = 0, + .parent = &perclk_clk, + .enable_reg = MXC_CRMAP_APRA, + .enable_shift = MXC_CRMAP_APRA_UART1EN_OFFSET, + .get_rate = clk_uart_get_rate, + .enable = _clk_1bit_enable, + .disable = _clk_1bit_disable, + }, { + .id = 1, + .parent = &perclk_clk, + .enable_reg = MXC_CRMAP_APRA, + .enable_shift = MXC_CRMAP_APRA_UART2EN_OFFSET, + .get_rate = clk_uart_get_rate, + .enable = _clk_1bit_enable, + .disable = _clk_1bit_disable, + }, { + .id = 2, + .parent = &perclk_clk, + .enable_reg = MXC_CRMAP_APRA, + .enable_shift = MXC_CRMAP_APRA_UART3EN_OFFSET, + .get_rate = clk_uart_get_rate, + .enable = _clk_1bit_enable, + .disable = _clk_1bit_disable, + }, +}; +/* uart_clk stuff end */ + +/* sdhc_clk stuff */ +static struct clk nfc_clk; + +static unsigned long clk_nfc_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / + CRM_1DIVIDER(MXC_CRMAP_ACDER2, NFCDIV); +} + +static struct clk nfc_clk = { + .parent = &ahb_clk, + .enable_reg = MXC_CRMAP_ACDER2, + .enable_shift = MXC_CRMAP_ACDER2_NFCEN_OFFSET, + .get_rate = clk_nfc_get_rate, + .enable = _clk_1bit_enable, + .disable = _clk_1bit_disable, +}; +/* sdhc_clk stuff end */ + +/* sdhc_clk stuff */ +static struct clk sdhc_clk[]; + +static struct clk *clk_sdhc_parent(struct clk *clk) +{ + u32 aprb; + u8 sel; + u32 mask; + int offset; + + aprb = __raw_readl(MXC_CRMAP_APRB); + + switch (clk->id) { + case 0: + mask = MXC_CRMAP_APRB_SDHC1_ISEL_MASK; + offset = MXC_CRMAP_APRB_SDHC1_ISEL_OFFSET; + break; + case 1: + mask = MXC_CRMAP_APRB_SDHC2_ISEL_MASK; + offset = MXC_CRMAP_APRB_SDHC2_ISEL_OFFSET; + break; + default: + BUG(); + } + sel = (aprb & mask) >> offset; + + switch (sel) { + case 0: + return &ckih_clk; + case 1: + return &ckih_x2_clk; + } + return &usb_clk; +} + +static unsigned long clk_sdhc_get_rate(struct clk *clk) +{ + u32 div; + + switch (clk->id) { + case 0: + div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRB, SDHC1_DIV); + break; + case 1: + div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRB, SDHC2_DIV); + break; + default: + BUG(); + } + + return clk_get_rate(clk->parent) / div; +} + +static int clk_sdhc_enable(struct clk *clk) +{ + u32 amlpmre1, aprb; + + amlpmre1 = __raw_readl(MXC_CRMAP_AMLPMRE1); + aprb = __raw_readl(MXC_CRMAP_APRB); + switch (clk->id) { + case 0: + amlpmre1 |= (0x7 << MXC_CRMAP_AMLPMRE1_MLPME4_OFFSET); + aprb |= (0x1 << MXC_CRMAP_APRB_SDHC1EN_OFFSET); + break; + case 1: + amlpmre1 |= (0x7 << MXC_CRMAP_AMLPMRE1_MLPME5_OFFSET); + aprb |= (0x1 << MXC_CRMAP_APRB_SDHC2EN_OFFSET); + break; + } + __raw_writel(amlpmre1, MXC_CRMAP_AMLPMRE1); + __raw_writel(aprb, MXC_CRMAP_APRB); + return 0; +} + +static void clk_sdhc_disable(struct clk *clk) +{ + u32 amlpmre1, aprb; + + amlpmre1 = __raw_readl(MXC_CRMAP_AMLPMRE1); + aprb = __raw_readl(MXC_CRMAP_APRB); + switch (clk->id) { + case 0: + amlpmre1 &= ~(0x7 << MXC_CRMAP_AMLPMRE1_MLPME4_OFFSET); + aprb &= ~(0x1 << MXC_CRMAP_APRB_SDHC1EN_OFFSET); + break; + case 1: + amlpmre1 &= ~(0x7 << MXC_CRMAP_AMLPMRE1_MLPME5_OFFSET); + aprb &= ~(0x1 << MXC_CRMAP_APRB_SDHC2EN_OFFSET); + break; + } + __raw_writel(amlpmre1, MXC_CRMAP_AMLPMRE1); + __raw_writel(aprb, MXC_CRMAP_APRB); +} + +static struct clk sdhc_clk[] = { + { + .id = 0, + .get_rate = clk_sdhc_get_rate, + .enable = clk_sdhc_enable, + .disable = clk_sdhc_disable, + }, { + .id = 1, + .get_rate = clk_sdhc_get_rate, + .enable = clk_sdhc_enable, + .disable = clk_sdhc_disable, + }, +}; +/* sdhc_clk stuff end */ + +/* wdog_clk stuff */ +static struct clk wdog_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CRMAP_AMLPMRD, + .enable_shift = MXC_CRMAP_AMLPMRD_MLPMD7_OFFSET, + .enable = _clk_3bit_enable, + .disable = _clk_3bit_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable_reg = MXC_CRMAP_AMLPMRD, + .enable_shift = MXC_CRMAP_AMLPMRD_MLPMD3_OFFSET, + .enable = _clk_3bit_enable, + .disable = _clk_3bit_disable, + }, +}; +/* wdog_clk stuff end */ + +/* gpt_clk stuff */ +static struct clk gpt_clk = { + .parent = &ipg_clk, + .enable_reg = MXC_CRMAP_AMLPMRC, + .enable_shift = MXC_CRMAP_AMLPMRC_MLPMC4_OFFSET, + .enable = _clk_3bit_enable, + .disable = _clk_3bit_disable, +}; +/* gpt_clk stuff end */ + +/* cspi_clk stuff */ +static struct clk cspi_clk[] = { + { + .id = 0, + .parent = &ipg_clk, + .enable_reg = MXC_CRMAP_AMLPMRE2, + .enable_shift = MXC_CRMAP_AMLPMRE2_MLPME0_OFFSET, + .enable = _clk_3bit_enable, + .disable = _clk_3bit_disable, + }, { + .id = 1, + .parent = &ipg_clk, + .enable_reg = MXC_CRMAP_AMLPMRE1, + .enable_shift = MXC_CRMAP_AMLPMRE1_MLPME6_OFFSET, + .enable = _clk_3bit_enable, + .disable = _clk_3bit_disable, + }, +}; +/* cspi_clk stuff end */ + +#define _REGISTER_CLOCK(d, n, c) \ + { \ + .dev_id = d, \ + .con_id = n, \ + .clk = &c, \ + }, + +static struct clk_lookup lookups[] = { + _REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0]) + _REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1]) + _REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2]) + _REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc_clk[0]) + _REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc_clk[1]) + _REGISTER_CLOCK("mxc-wdt.0", NULL, wdog_clk[0]) + _REGISTER_CLOCK("spi_imx.0", NULL, cspi_clk[0]) + _REGISTER_CLOCK("spi_imx.1", NULL, cspi_clk[1]) +}; + +int __init mxc91231_clocks_init(unsigned long fref) +{ + void __iomem *gpt_base; + int i; + + ckih_rate = fref; + + usb_clk.parent = clk_usb_parent(&usb_clk); + sdhc_clk[0].parent = clk_sdhc_parent(&sdhc_clk[0]); + sdhc_clk[1].parent = clk_sdhc_parent(&sdhc_clk[1]); + + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); + + gpt_base = MXC91231_IO_ADDRESS(MXC91231_GPT1_BASE_ADDR); + mxc_timer_init(&gpt_clk, gpt_base, MXC91231_INT_GPT); + + return 0; +} diff --git a/arch/arm/mach-mxc91231/crm_regs.h b/arch/arm/mach-mxc91231/crm_regs.h new file mode 100644 index 000000000000..ce4f59058189 --- /dev/null +++ b/arch/arm/mach-mxc91231/crm_regs.h @@ -0,0 +1,399 @@ +/* + * Copyright 2006 Freescale Semiconductor, Inc. + * Copyright 2006-2007 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _ARCH_ARM_MACH_MXC91231_CRM_REGS_H_ +#define _ARCH_ARM_MACH_MXC91231_CRM_REGS_H_ + +#define CKIL_CLK_FREQ 32768 + +#define MXC_CRM_AP_BASE MXC91231_IO_ADDRESS(MXC91231_CRM_AP_BASE_ADDR) +#define MXC_CRM_COM_BASE MXC91231_IO_ADDRESS(MXC91231_CRM_COM_BASE_ADDR) +#define MXC_DSM_BASE MXC91231_IO_ADDRESS(MXC91231_DSM_BASE_ADDR) +#define MXC_PLL0_BASE MXC91231_IO_ADDRESS(MXC91231_PLL0_BASE_ADDR) +#define MXC_PLL1_BASE MXC91231_IO_ADDRESS(MXC91231_PLL1_BASE_ADDR) +#define MXC_PLL2_BASE MXC91231_IO_ADDRESS(MXC91231_PLL2_BASE_ADDR) +#define MXC_CLKCTL_BASE MXC91231_IO_ADDRESS(MXC91231_CLKCTL_BASE_ADDR) + +/* PLL Register Offsets */ +#define MXC_PLL_DP_CTL 0x00 +#define MXC_PLL_DP_CONFIG 0x04 +#define MXC_PLL_DP_OP 0x08 +#define MXC_PLL_DP_MFD 0x0C +#define MXC_PLL_DP_MFN 0x10 +#define MXC_PLL_DP_HFS_OP 0x1C +#define MXC_PLL_DP_HFS_MFD 0x20 +#define MXC_PLL_DP_HFS_MFN 0x24 + +/* PLL Register Bit definitions */ +#define MXC_PLL_DP_CTL_DPDCK0_2_EN 0x1000 +#define MXC_PLL_DP_CTL_ADE 0x800 +#define MXC_PLL_DP_CTL_REF_CLK_DIV 0x400 +#define MXC_PLL_DP_CTL_HFSM 0x80 +#define MXC_PLL_DP_CTL_PRE 0x40 +#define MXC_PLL_DP_CTL_UPEN 0x20 +#define MXC_PLL_DP_CTL_RST 0x10 +#define MXC_PLL_DP_CTL_RCP 0x8 +#define MXC_PLL_DP_CTL_PLM 0x4 +#define MXC_PLL_DP_CTL_BRM0 0x2 +#define MXC_PLL_DP_CTL_LRF 0x1 + +#define MXC_PLL_DP_OP_MFI_OFFSET 4 +#define MXC_PLL_DP_OP_MFI_MASK 0xF +#define MXC_PLL_DP_OP_PDF_OFFSET 0 +#define MXC_PLL_DP_OP_PDF_MASK 0xF + +#define MXC_PLL_DP_MFD_OFFSET 0 +#define MXC_PLL_DP_MFD_MASK 0x7FFFFFF + +#define MXC_PLL_DP_MFN_OFFSET 0 +#define MXC_PLL_DP_MFN_MASK 0x7FFFFFF + +/* CRM AP Register Offsets */ +#define MXC_CRMAP_ASCSR (MXC_CRM_AP_BASE + 0x00) +#define MXC_CRMAP_ACDR (MXC_CRM_AP_BASE + 0x04) +#define MXC_CRMAP_ACDER1 (MXC_CRM_AP_BASE + 0x08) +#define MXC_CRMAP_ACDER2 (MXC_CRM_AP_BASE + 0x0C) +#define MXC_CRMAP_ACGCR (MXC_CRM_AP_BASE + 0x10) +#define MXC_CRMAP_ACCGCR (MXC_CRM_AP_BASE + 0x14) +#define MXC_CRMAP_AMLPMRA (MXC_CRM_AP_BASE + 0x18) +#define MXC_CRMAP_AMLPMRB (MXC_CRM_AP_BASE + 0x1C) +#define MXC_CRMAP_AMLPMRC (MXC_CRM_AP_BASE + 0x20) +#define MXC_CRMAP_AMLPMRD (MXC_CRM_AP_BASE + 0x24) +#define MXC_CRMAP_AMLPMRE1 (MXC_CRM_AP_BASE + 0x28) +#define MXC_CRMAP_AMLPMRE2 (MXC_CRM_AP_BASE + 0x2C) +#define MXC_CRMAP_AMLPMRF (MXC_CRM_AP_BASE + 0x30) +#define MXC_CRMAP_AMLPMRG (MXC_CRM_AP_BASE + 0x34) +#define MXC_CRMAP_APGCR (MXC_CRM_AP_BASE + 0x38) +#define MXC_CRMAP_ACSR (MXC_CRM_AP_BASE + 0x3C) +#define MXC_CRMAP_ADCR (MXC_CRM_AP_BASE + 0x40) +#define MXC_CRMAP_ACR (MXC_CRM_AP_BASE + 0x44) +#define MXC_CRMAP_AMCR (MXC_CRM_AP_BASE + 0x48) +#define MXC_CRMAP_APCR (MXC_CRM_AP_BASE + 0x4C) +#define MXC_CRMAP_AMORA (MXC_CRM_AP_BASE + 0x50) +#define MXC_CRMAP_AMORB (MXC_CRM_AP_BASE + 0x54) +#define MXC_CRMAP_AGPR (MXC_CRM_AP_BASE + 0x58) +#define MXC_CRMAP_APRA (MXC_CRM_AP_BASE + 0x5C) +#define MXC_CRMAP_APRB (MXC_CRM_AP_BASE + 0x60) +#define MXC_CRMAP_APOR (MXC_CRM_AP_BASE + 0x64) +#define MXC_CRMAP_ADFMR (MXC_CRM_AP_BASE + 0x68) + +/* CRM AP Register Bit definitions */ +#define MXC_CRMAP_ASCSR_CRS 0x10000 +#define MXC_CRMAP_ASCSR_AP_PATDIV2_OFFSET 15 +#define MXC_CRMAP_ASCSR_AP_PATREF_DIV2 0x8000 +#define MXC_CRMAP_ASCSR_USBSEL_OFFSET 13 +#define MXC_CRMAP_ASCSR_USBSEL_MASK (0x3 << 13) +#define MXC_CRMAP_ASCSR_CSISEL_OFFSET 11 +#define MXC_CRMAP_ASCSR_CSISEL_MASK (0x3 << 11) +#define MXC_CRMAP_ASCSR_SSI2SEL_OFFSET 7 +#define MXC_CRMAP_ASCSR_SSI2SEL_MASK (0x3 << 7) +#define MXC_CRMAP_ASCSR_SSI1SEL_OFFSET 5 +#define MXC_CRMAP_ASCSR_SSI1SEL_MASK (0x3 << 5) +#define MXC_CRMAP_ASCSR_APSEL_OFFSET 3 +#define MXC_CRMAP_ASCSR_APSEL_MASK (0x3 << 3) +#define MXC_CRMAP_ASCSR_AP_PATDIV1_OFFSET 2 +#define MXC_CRMAP_ASCSR_AP_PATREF_DIV1 0x4 +#define MXC_CRMAP_ASCSR_APISEL 0x1 + +#define MXC_CRMAP_ACDR_ARMDIV_OFFSET 8 +#define MXC_CRMAP_ACDR_ARMDIV_MASK (0xF << 8) +#define MXC_CRMAP_ACDR_AHBDIV_OFFSET 4 +#define MXC_CRMAP_ACDR_AHBDIV_MASK (0xF << 4) +#define MXC_CRMAP_ACDR_IPDIV_OFFSET 0 +#define MXC_CRMAP_ACDR_IPDIV_MASK 0xF + +#define MXC_CRMAP_ACDER1_CSIEN_OFFSET 30 +#define MXC_CRMAP_ACDER1_CSIDIV_OFFSET 24 +#define MXC_CRMAP_ACDER1_CSIDIV_MASK (0x3F << 24) +#define MXC_CRMAP_ACDER1_SSI2EN_OFFSET 14 +#define MXC_CRMAP_ACDER1_SSI2DIV_OFFSET 8 +#define MXC_CRMAP_ACDER1_SSI2DIV_MASK (0x3F << 8) +#define MXC_CRMAP_ACDER1_SSI1EN_OFFSET 6 +#define MXC_CRMAP_ACDER1_SSI1DIV_OFFSET 0 +#define MXC_CRMAP_ACDER1_SSI1DIV_MASK 0x3F + +#define MXC_CRMAP_ACDER2_CRCT_CLK_DIV_OFFSET 24 +#define MXC_CRMAP_ACDER2_CRCT_CLK_DIV_MASK (0x7 << 24) +#define MXC_CRMAP_ACDER2_NFCEN_OFFSET 20 +#define MXC_CRMAP_ACDER2_NFCDIV_OFFSET 16 +#define MXC_CRMAP_ACDER2_NFCDIV_MASK (0xF << 16) +#define MXC_CRMAP_ACDER2_USBEN_OFFSET 12 +#define MXC_CRMAP_ACDER2_USBDIV_OFFSET 8 +#define MXC_CRMAP_ACDER2_USBDIV_MASK (0xF << 8) +#define MXC_CRMAP_ACDER2_BAUD_ISEL_OFFSET 5 +#define MXC_CRMAP_ACDER2_BAUD_ISEL_MASK (0x3 << 5) +#define MXC_CRMAP_ACDER2_BAUDDIV_OFFSET 0 +#define MXC_CRMAP_ACDER2_BAUDDIV_MASK 0xF + +#define MXC_CRMAP_AMLPMRA_MLPMA7_OFFSET 22 +#define MXC_CRMAP_AMLPMRA_MLPMA7_MASK (0x7 << 22) +#define MXC_CRMAP_AMLPMRA_MLPMA6_OFFSET 19 +#define MXC_CRMAP_AMLPMRA_MLPMA6_MASK (0x7 << 19) +#define MXC_CRMAP_AMLPMRA_MLPMA4_OFFSET 12 +#define MXC_CRMAP_AMLPMRA_MLPMA4_MASK (0x7 << 12) +#define MXC_CRMAP_AMLPMRA_MLPMA3_OFFSET 9 +#define MXC_CRMAP_AMLPMRA_MLPMA3_MASK (0x7 << 9) +#define MXC_CRMAP_AMLPMRA_MLPMA2_OFFSET 6 +#define MXC_CRMAP_AMLPMRA_MLPMA2_MASK (0x7 << 6) +#define MXC_CRMAP_AMLPMRA_MLPMA1_OFFSET 3 +#define MXC_CRMAP_AMLPMRA_MLPMA1_MASK (0x7 << 3) + +#define MXC_CRMAP_AMLPMRB_MLPMB0_OFFSET 0 +#define MXC_CRMAP_AMLPMRB_MLPMB0_MASK 0x7 + +#define MXC_CRMAP_AMLPMRC_MLPMC9_OFFSET 28 +#define MXC_CRMAP_AMLPMRC_MLPMC9_MASK (0x7 << 28) +#define MXC_CRMAP_AMLPMRC_MLPMC7_OFFSET 22 +#define MXC_CRMAP_AMLPMRC_MLPMC7_MASK (0x7 << 22) +#define MXC_CRMAP_AMLPMRC_MLPMC5_OFFSET 16 +#define MXC_CRMAP_AMLPMRC_MLPMC5_MASK (0x7 << 16) +#define MXC_CRMAP_AMLPMRC_MLPMC4_OFFSET 12 +#define MXC_CRMAP_AMLPMRC_MLPMC4_MASK (0x7 << 12) +#define MXC_CRMAP_AMLPMRC_MLPMC3_OFFSET 9 +#define MXC_CRMAP_AMLPMRC_MLPMC3_MASK (0x7 << 9) +#define MXC_CRMAP_AMLPMRC_MLPMC2_OFFSET 6 +#define MXC_CRMAP_AMLPMRC_MLPMC2_MASK (0x7 << 6) +#define MXC_CRMAP_AMLPMRC_MLPMC1_OFFSET 3 +#define MXC_CRMAP_AMLPMRC_MLPMC1_MASK (0x7 << 3) +#define MXC_CRMAP_AMLPMRC_MLPMC0_OFFSET 0 +#define MXC_CRMAP_AMLPMRC_MLPMC0_MASK 0x7 + +#define MXC_CRMAP_AMLPMRD_MLPMD7_OFFSET 22 +#define MXC_CRMAP_AMLPMRD_MLPMD7_MASK (0x7 << 22) +#define MXC_CRMAP_AMLPMRD_MLPMD4_OFFSET 12 +#define MXC_CRMAP_AMLPMRD_MLPMD4_MASK (0x7 << 12) +#define MXC_CRMAP_AMLPMRD_MLPMD3_OFFSET 9 +#define MXC_CRMAP_AMLPMRD_MLPMD3_MASK (0x7 << 9) +#define MXC_CRMAP_AMLPMRD_MLPMD2_OFFSET 6 +#define MXC_CRMAP_AMLPMRD_MLPMD2_MASK (0x7 << 6) +#define MXC_CRMAP_AMLPMRD_MLPMD0_OFFSET 0 +#define MXC_CRMAP_AMLPMRD_MLPMD0_MASK 0x7 + +#define MXC_CRMAP_AMLPMRE1_MLPME9_OFFSET 28 +#define MXC_CRMAP_AMLPMRE1_MLPME9_MASK (0x7 << 28) +#define MXC_CRMAP_AMLPMRE1_MLPME8_OFFSET 25 +#define MXC_CRMAP_AMLPMRE1_MLPME8_MASK (0x7 << 25) +#define MXC_CRMAP_AMLPMRE1_MLPME7_OFFSET 22 +#define MXC_CRMAP_AMLPMRE1_MLPME7_MASK (0x7 << 22) +#define MXC_CRMAP_AMLPMRE1_MLPME6_OFFSET 19 +#define MXC_CRMAP_AMLPMRE1_MLPME6_MASK (0x7 << 19) +#define MXC_CRMAP_AMLPMRE1_MLPME5_OFFSET 16 +#define MXC_CRMAP_AMLPMRE1_MLPME5_MASK (0x7 << 16) +#define MXC_CRMAP_AMLPMRE1_MLPME4_OFFSET 12 +#define MXC_CRMAP_AMLPMRE1_MLPME4_MASK (0x7 << 12) +#define MXC_CRMAP_AMLPMRE1_MLPME3_OFFSET 9 +#define MXC_CRMAP_AMLPMRE1_MLPME3_MASK (0x7 << 9) +#define MXC_CRMAP_AMLPMRE1_MLPME2_OFFSET 6 +#define MXC_CRMAP_AMLPMRE1_MLPME2_MASK (0x7 << 6) +#define MXC_CRMAP_AMLPMRE1_MLPME1_OFFSET 3 +#define MXC_CRMAP_AMLPMRE1_MLPME1_MASK (0x7 << 3) +#define MXC_CRMAP_AMLPMRE1_MLPME0_OFFSET 0 +#define MXC_CRMAP_AMLPMRE1_MLPME0_MASK 0x7 + +#define MXC_CRMAP_AMLPMRE2_MLPME0_OFFSET 0 +#define MXC_CRMAP_AMLPMRE2_MLPME0_MASK 0x7 + +#define MXC_CRMAP_AMLPMRF_MLPMF6_OFFSET 19 +#define MXC_CRMAP_AMLPMRF_MLPMF6_MASK (0x7 << 19) +#define MXC_CRMAP_AMLPMRF_MLPMF5_OFFSET 16 +#define MXC_CRMAP_AMLPMRF_MLPMF5_MASK (0x7 << 16) +#define MXC_CRMAP_AMLPMRF_MLPMF3_OFFSET 9 +#define MXC_CRMAP_AMLPMRF_MLPMF3_MASK (0x7 << 9) +#define MXC_CRMAP_AMLPMRF_MLPMF2_OFFSET 6 +#define MXC_CRMAP_AMLPMRF_MLPMF2_MASK (0x7 << 6) +#define MXC_CRMAP_AMLPMRF_MLPMF1_OFFSET 3 +#define MXC_CRMAP_AMLPMRF_MLPMF1_MASK (0x7 << 3) +#define MXC_CRMAP_AMLPMRF_MLPMF0_OFFSET 0 +#define MXC_CRMAP_AMLPMRF_MLPMF0_MASK (0x7 << 0) + +#define MXC_CRMAP_AMLPMRG_MLPMG9_OFFSET 28 +#define MXC_CRMAP_AMLPMRG_MLPMG9_MASK (0x7 << 28) +#define MXC_CRMAP_AMLPMRG_MLPMG7_OFFSET 22 +#define MXC_CRMAP_AMLPMRG_MLPMG7_MASK (0x7 << 22) +#define MXC_CRMAP_AMLPMRG_MLPMG6_OFFSET 19 +#define MXC_CRMAP_AMLPMRG_MLPMG6_MASK (0x7 << 19) +#define MXC_CRMAP_AMLPMRG_MLPMG5_OFFSET 16 +#define MXC_CRMAP_AMLPMRG_MLPMG5_MASK (0x7 << 16) +#define MXC_CRMAP_AMLPMRG_MLPMG4_OFFSET 12 +#define MXC_CRMAP_AMLPMRG_MLPMG4_MASK (0x7 << 12) +#define MXC_CRMAP_AMLPMRG_MLPMG3_OFFSET 9 +#define MXC_CRMAP_AMLPMRG_MLPMG3_MASK (0x7 << 9) +#define MXC_CRMAP_AMLPMRG_MLPMG2_OFFSET 6 +#define MXC_CRMAP_AMLPMRG_MLPMG2_MASK (0x7 << 6) +#define MXC_CRMAP_AMLPMRG_MLPMG1_OFFSET 3 +#define MXC_CRMAP_AMLPMRG_MLPMG1_MASK (0x7 << 3) +#define MXC_CRMAP_AMLPMRG_MLPMG0_OFFSET 0 +#define MXC_CRMAP_AMLPMRG_MLPMG0_MASK 0x7 + +#define MXC_CRMAP_AGPR_IPUPAD_OFFSET 20 +#define MXC_CRMAP_AGPR_IPUPAD_MASK (0x7 << 20) + +#define MXC_CRMAP_APRA_EL1TEN_OFFSET 29 +#define MXC_CRMAP_APRA_SIMEN_OFFSET 24 +#define MXC_CRMAP_APRA_UART3DIV_OFFSET 17 +#define MXC_CRMAP_APRA_UART3DIV_MASK (0xF << 17) +#define MXC_CRMAP_APRA_UART3EN_OFFSET 16 +#define MXC_CRMAP_APRA_SAHARA_DIV2_CLKEN_OFFSET 14 +#define MXC_CRMAP_APRA_MQSPIEN_OFFSET 13 +#define MXC_CRMAP_APRA_UART2EN_OFFSET 8 +#define MXC_CRMAP_APRA_UART1EN_OFFSET 0 + +#define MXC_CRMAP_APRB_SDHC2_ISEL_OFFSET 13 +#define MXC_CRMAP_APRB_SDHC2_ISEL_MASK (0x7 << 13) +#define MXC_CRMAP_APRB_SDHC2_DIV_OFFSET 9 +#define MXC_CRMAP_APRB_SDHC2_DIV_MASK (0xF << 9) +#define MXC_CRMAP_APRB_SDHC2EN_OFFSET 8 +#define MXC_CRMAP_APRB_SDHC1_ISEL_OFFSET 5 +#define MXC_CRMAP_APRB_SDHC1_ISEL_MASK (0x7 << 5) +#define MXC_CRMAP_APRB_SDHC1_DIV_OFFSET 1 +#define MXC_CRMAP_APRB_SDHC1_DIV_MASK (0xF << 1) +#define MXC_CRMAP_APRB_SDHC1EN_OFFSET 0 + +#define MXC_CRMAP_ACSR_ADS_OFFSET 8 +#define MXC_CRMAP_ACSR_ADS (0x1 << 8) +#define MXC_CRMAP_ACSR_ACS 0x1 + +#define MXC_CRMAP_ADCR_LFDF_0 (0x0 << 8) +#define MXC_CRMAP_ADCR_LFDF_2 (0x1 << 8) +#define MXC_CRMAP_ADCR_LFDF_4 (0x2 << 8) +#define MXC_CRMAP_ADCR_LFDF_8 (0x3 << 8) +#define MXC_CRMAP_ADCR_LFDF_OFFSET 8 +#define MXC_CRMAP_ADCR_LFDF_MASK (0x3 << 8) +#define MXC_CRMAP_ADCR_ALT_PLL 0x80 +#define MXC_CRMAP_ADCR_DFS_DIVEN 0x20 +#define MXC_CRMAP_ADCR_DIV_BYP 0x2 +#define MXC_CRMAP_ADCR_VSTAT 0x8 +#define MXC_CRMAP_ADCR_TSTAT 0x10 +#define MXC_CRMAP_ADCR_DVFS_VCTRL 0x10 +#define MXC_CRMAP_ADCR_CLK_ON 0x40 + +#define MXC_CRMAP_ADFMR_FC_OFFSET 16 +#define MXC_CRMAP_ADFMR_FC_MASK (0x1F << 16) +#define MXC_CRMAP_ADFMR_MF_OFFSET 1 +#define MXC_CRMAP_ADFMR_MF_MASK (0x3FF << 1) +#define MXC_CRMAP_ADFMR_DFM_CLK_READY 0x1 +#define MXC_CRMAP_ADFMR_DFM_PWR_DOWN 0x8000 + +#define MXC_CRMAP_ACR_CKOHS_HIGH (1 << 18) +#define MXC_CRMAP_ACR_CKOS_HIGH (1 << 16) +#define MXC_CRMAP_ACR_CKOHS_MASK (0x7 << 12) +#define MXC_CRMAP_ACR_CKOHD (1 << 11) +#define MXC_CRMAP_ACR_CKOHDIV_MASK (0xF << 8) +#define MXC_CRMAP_ACR_CKOHDIV_OFFSET 8 +#define MXC_CRMAP_ACR_CKOD (1 << 7) +#define MXC_CRMAP_ACR_CKOS_MASK (0x7 << 4) + +/* AP Warm reset */ +#define MXC_CRMAP_AMCR_SW_AP (1 << 14) + +/* Bit definitions of ACGCR in CRM_AP for tree level clock gating */ +#define MXC_CRMAP_ACGCR_ACG0_STOP_WAIT 0x00000001 +#define MXC_CRMAP_ACGCR_ACG0_STOP 0x00000003 +#define MXC_CRMAP_ACGCR_ACG0_RUN 0x00000007 +#define MXC_CRMAP_ACGCR_ACG0_DISABLED 0x00000000 + +#define MXC_CRMAP_ACGCR_ACG1_STOP_WAIT 0x00000008 +#define MXC_CRMAP_ACGCR_ACG1_STOP 0x00000018 +#define MXC_CRMAP_ACGCR_ACG1_RUN 0x00000038 +#define MXC_CRMAP_ACGCR_ACG1_DISABLED 0x00000000 + +#define MXC_CRMAP_ACGCR_ACG2_STOP_WAIT 0x00000040 +#define MXC_CRMAP_ACGCR_ACG2_STOP 0x000000C0 +#define MXC_CRMAP_ACGCR_ACG2_RUN 0x000001C0 +#define MXC_CRMAP_ACGCR_ACG2_DISABLED 0x00000000 + +#define MXC_CRMAP_ACGCR_ACG3_STOP_WAIT 0x00000200 +#define MXC_CRMAP_ACGCR_ACG3_STOP 0x00000600 +#define MXC_CRMAP_ACGCR_ACG3_RUN 0x00000E00 +#define MXC_CRMAP_ACGCR_ACG3_DISABLED 0x00000000 + +#define MXC_CRMAP_ACGCR_ACG4_STOP_WAIT 0x00001000 +#define MXC_CRMAP_ACGCR_ACG4_STOP 0x00003000 +#define MXC_CRMAP_ACGCR_ACG4_RUN 0x00007000 +#define MXC_CRMAP_ACGCR_ACG4_DISABLED 0x00000000 + +#define MXC_CRMAP_ACGCR_ACG5_STOP_WAIT 0x00010000 +#define MXC_CRMAP_ACGCR_ACG5_STOP 0x00030000 +#define MXC_CRMAP_ACGCR_ACG5_RUN 0x00070000 +#define MXC_CRMAP_ACGCR_ACG5_DISABLED 0x00000000 + +#define MXC_CRMAP_ACGCR_ACG6_STOP_WAIT 0x00080000 +#define MXC_CRMAP_ACGCR_ACG6_STOP 0x00180000 +#define MXC_CRMAP_ACGCR_ACG6_RUN 0x00380000 +#define MXC_CRMAP_ACGCR_ACG6_DISABLED 0x00000000 + +#define NUM_GATE_CTRL 6 + +/* CRM COM Register Offsets */ +#define MXC_CRMCOM_CSCR (MXC_CRM_COM_BASE + 0x0C) +#define MXC_CRMCOM_CCCR (MXC_CRM_COM_BASE + 0x10) + +/* CRM COM Bit Definitions */ +#define MXC_CRMCOM_CSCR_PPD1 0x08000000 +#define MXC_CRMCOM_CSCR_CKOHSEL (1 << 18) +#define MXC_CRMCOM_CSCR_CKOSEL (1 << 17) +#define MXC_CRMCOM_CCCR_CC_DIV_OFFSET 8 +#define MXC_CRMCOM_CCCR_CC_DIV_MASK (0x1F << 8) +#define MXC_CRMCOM_CCCR_CC_SEL_OFFSET 0 +#define MXC_CRMCOM_CCCR_CC_SEL_MASK 0x3 + +/* DSM Register Offsets */ +#define MXC_DSM_SLEEP_TIME (MXC_DSM_BASE + 0x0c) +#define MXC_DSM_CONTROL0 (MXC_DSM_BASE + 0x20) +#define MXC_DSM_CONTROL1 (MXC_DSM_BASE + 0x24) +#define MXC_DSM_CTREN (MXC_DSM_BASE + 0x28) +#define MXC_DSM_WARM_PER (MXC_DSM_BASE + 0x40) +#define MXC_DSM_LOCK_PER (MXC_DSM_BASE + 0x44) +#define MXC_DSM_MGPER (MXC_DSM_BASE + 0x4c) +#define MXC_DSM_CRM_CONTROL (MXC_DSM_BASE + 0x50) + +/* Bit definitions of various registers in DSM */ +#define MXC_DSM_CRM_CTRL_DVFS_BYP 0x00000008 +#define MXC_DSM_CRM_CTRL_DVFS_VCTRL 0x00000004 +#define MXC_DSM_CRM_CTRL_LPMD1 0x00000002 +#define MXC_DSM_CRM_CTRL_LPMD0 0x00000001 +#define MXC_DSM_CRM_CTRL_LPMD_STOP_MODE 0x00000000 +#define MXC_DSM_CRM_CTRL_LPMD_WAIT_MODE 0x00000001 +#define MXC_DSM_CRM_CTRL_LPMD_RUN_MODE 0x00000003 +#define MXC_DSM_CONTROL0_STBY_COMMIT_EN 0x00000200 +#define MXC_DSM_CONTROL0_MSTR_EN 0x00000001 +#define MXC_DSM_CONTROL0_RESTART 0x00000010 +/* Counter Block reset */ +#define MXC_DSM_CONTROL1_CB_RST 0x00000002 +/* State Machine reset */ +#define MXC_DSM_CONTROL1_SM_RST 0x00000004 +/* Bit needed to reset counter block */ +#define MXC_CONTROL1_RST_CNT32 0x00000008 +#define MXC_DSM_CONTROL1_RST_CNT32_EN 0x00000800 +#define MXC_DSM_CONTROL1_SLEEP 0x00000100 +#define MXC_DSM_CONTROL1_WAKEUP_DISABLE 0x00004000 +#define MXC_DSM_CTREN_CNT32 0x00000001 + +/* Magic Fix enable bit */ +#define MXC_DSM_MGPER_EN_MGFX 0x80000000 +#define MXC_DSM_MGPER_PER_MASK 0x000003FF +#define MXC_DSM_MGPER_PER(n) (MXC_DSM_MGPER_PER_MASK & n) + +/* Address offsets of the CLKCTL registers */ +#define MXC_CLKCTL_GP_CTRL (MXC_CLKCTL_BASE + 0x00) +#define MXC_CLKCTL_GP_SER (MXC_CLKCTL_BASE + 0x04) +#define MXC_CLKCTL_GP_CER (MXC_CLKCTL_BASE + 0x08) + +#endif /* _ARCH_ARM_MACH_MXC91231_CRM_REGS_H_ */ diff --git a/arch/arm/mach-mxc91231/devices.c b/arch/arm/mach-mxc91231/devices.c new file mode 100644 index 000000000000..353bd977b393 --- /dev/null +++ b/arch/arm/mach-mxc91231/devices.c @@ -0,0 +1,251 @@ +/* + * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Sascha Hauer, kernel@pengutronix.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/serial.h> +#include <linux/gpio.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/imx-uart.h> + +static struct resource uart0[] = { + { + .start = MXC91231_UART1_BASE_ADDR, + .end = MXC91231_UART1_BASE_ADDR + 0x0B5, + .flags = IORESOURCE_MEM, + }, { + .start = MXC91231_INT_UART1_RX, + .end = MXC91231_INT_UART1_RX, + .flags = IORESOURCE_IRQ, + }, { + .start = MXC91231_INT_UART1_TX, + .end = MXC91231_INT_UART1_TX, + .flags = IORESOURCE_IRQ, + }, { + .start = MXC91231_INT_UART1_MINT, + .end = MXC91231_INT_UART1_MINT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_uart_device0 = { + .name = "imx-uart", + .id = 0, + .resource = uart0, + .num_resources = ARRAY_SIZE(uart0), +}; + +static struct resource uart1[] = { + { + .start = MXC91231_UART2_BASE_ADDR, + .end = MXC91231_UART2_BASE_ADDR + 0x0B5, + .flags = IORESOURCE_MEM, + }, { + .start = MXC91231_INT_UART2_RX, + .end = MXC91231_INT_UART2_RX, + .flags = IORESOURCE_IRQ, + }, { + .start = MXC91231_INT_UART2_TX, + .end = MXC91231_INT_UART2_TX, + .flags = IORESOURCE_IRQ, + }, { + .start = MXC91231_INT_UART2_MINT, + .end = MXC91231_INT_UART2_MINT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_uart_device1 = { + .name = "imx-uart", + .id = 1, + .resource = uart1, + .num_resources = ARRAY_SIZE(uart1), +}; + +static struct resource uart2[] = { + { + .start = MXC91231_UART3_BASE_ADDR, + .end = MXC91231_UART3_BASE_ADDR + 0x0B5, + .flags = IORESOURCE_MEM, + }, { + .start = MXC91231_INT_UART3_RX, + .end = MXC91231_INT_UART3_RX, + .flags = IORESOURCE_IRQ, + }, { + .start = MXC91231_INT_UART3_TX, + .end = MXC91231_INT_UART3_TX, + .flags = IORESOURCE_IRQ, + }, { + .start = MXC91231_INT_UART3_MINT, + .end = MXC91231_INT_UART3_MINT, + .flags = IORESOURCE_IRQ, + + }, +}; + +struct platform_device mxc_uart_device2 = { + .name = "imx-uart", + .id = 2, + .resource = uart2, + .num_resources = ARRAY_SIZE(uart2), +}; + +/* GPIO port description */ +static struct mxc_gpio_port mxc_gpio_ports[] = { + [0] = { + .chip.label = "gpio-0", + .base = MXC91231_IO_ADDRESS(MXC91231_GPIO1_AP_BASE_ADDR), + .irq = MXC91231_INT_GPIO1, + .virtual_irq_start = MXC_GPIO_IRQ_START, + }, + [1] = { + .chip.label = "gpio-1", + .base = MXC91231_IO_ADDRESS(MXC91231_GPIO2_AP_BASE_ADDR), + .irq = MXC91231_INT_GPIO2, + .virtual_irq_start = MXC_GPIO_IRQ_START + 32, + }, + [2] = { + .chip.label = "gpio-2", + .base = MXC91231_IO_ADDRESS(MXC91231_GPIO3_AP_BASE_ADDR), + .irq = MXC91231_INT_GPIO3, + .virtual_irq_start = MXC_GPIO_IRQ_START + 64, + }, + [3] = { + .chip.label = "gpio-3", + .base = MXC91231_IO_ADDRESS(MXC91231_GPIO4_SH_BASE_ADDR), + .irq = MXC91231_INT_GPIO4, + .virtual_irq_start = MXC_GPIO_IRQ_START + 96, + }, +}; + +int __init mxc_register_gpios(void) +{ + return mxc_gpio_init(mxc_gpio_ports, ARRAY_SIZE(mxc_gpio_ports)); +} + +static struct resource mxc_nand_resources[] = { + { + .start = MXC91231_NFC_BASE_ADDR, + .end = MXC91231_NFC_BASE_ADDR + 0xfff, + .flags = IORESOURCE_MEM + }, { + .start = MXC91231_INT_NANDFC, + .end = MXC91231_INT_NANDFC, + .flags = IORESOURCE_IRQ + }, +}; + +struct platform_device mxc_nand_device = { + .name = "mxc_nand", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_nand_resources), + .resource = mxc_nand_resources, +}; + +static struct resource mxc_sdhc0_resources[] = { + { + .start = MXC91231_MMC_SDHC1_BASE_ADDR, + .end = MXC91231_MMC_SDHC1_BASE_ADDR + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC91231_INT_MMC_SDHC1, + .end = MXC91231_INT_MMC_SDHC1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource mxc_sdhc1_resources[] = { + { + .start = MXC91231_MMC_SDHC2_BASE_ADDR, + .end = MXC91231_MMC_SDHC2_BASE_ADDR + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = MXC91231_INT_MMC_SDHC2, + .end = MXC91231_INT_MMC_SDHC2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_sdhc_device0 = { + .name = "mxc-mmc", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_sdhc0_resources), + .resource = mxc_sdhc0_resources, +}; + +struct platform_device mxc_sdhc_device1 = { + .name = "mxc-mmc", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_sdhc1_resources), + .resource = mxc_sdhc1_resources, +}; + +static struct resource mxc_cspi0_resources[] = { + { + .start = MXC91231_CSPI1_BASE_ADDR, + .end = MXC91231_CSPI1_BASE_ADDR + 0x20, + .flags = IORESOURCE_MEM, + }, { + .start = MXC91231_INT_CSPI1, + .end = MXC91231_INT_CSPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_cspi_device0 = { + .name = "spi_imx", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_cspi0_resources), + .resource = mxc_cspi0_resources, +}; + +static struct resource mxc_cspi1_resources[] = { + { + .start = MXC91231_CSPI2_BASE_ADDR, + .end = MXC91231_CSPI2_BASE_ADDR + 0x20, + .flags = IORESOURCE_MEM, + }, { + .start = MXC91231_INT_CSPI2, + .end = MXC91231_INT_CSPI2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device mxc_cspi_device1 = { + .name = "spi_imx", + .id = 1, + .num_resources = ARRAY_SIZE(mxc_cspi1_resources), + .resource = mxc_cspi1_resources, +}; + +static struct resource mxc_wdog0_resources[] = { + { + .start = MXC91231_WDOG1_BASE_ADDR, + .end = MXC91231_WDOG1_BASE_ADDR + 0x10, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device mxc_wdog_device0 = { + .name = "mxc-wdt", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_wdog0_resources), + .resource = mxc_wdog0_resources, +}; diff --git a/arch/arm/mach-mxc91231/devices.h b/arch/arm/mach-mxc91231/devices.h new file mode 100644 index 000000000000..72a2136ce27d --- /dev/null +++ b/arch/arm/mach-mxc91231/devices.h @@ -0,0 +1,13 @@ +extern struct platform_device mxc_uart_device0; +extern struct platform_device mxc_uart_device1; +extern struct platform_device mxc_uart_device2; + +extern struct platform_device mxc_nand_device; + +extern struct platform_device mxc_sdhc_device0; +extern struct platform_device mxc_sdhc_device1; + +extern struct platform_device mxc_cspi_device0; +extern struct platform_device mxc_cspi_device1; + +extern struct platform_device mxc_wdog_device0; diff --git a/arch/arm/mach-mxc91231/iomux.c b/arch/arm/mach-mxc91231/iomux.c new file mode 100644 index 000000000000..405d9b19d891 --- /dev/null +++ b/arch/arm/mach-mxc91231/iomux.c @@ -0,0 +1,177 @@ +/* + * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> + * Copyright (C) 2009 by Valentin Longchamp <valentin.longchamp@epfl.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <mach/hardware.h> +#include <mach/gpio.h> +#include <mach/iomux-mxc91231.h> + +/* + * IOMUX register (base) addresses + */ +#define IOMUX_AP_BASE MXC91231_IO_ADDRESS(MXC91231_IOMUX_AP_BASE_ADDR) +#define IOMUX_COM_BASE MXC91231_IO_ADDRESS(MXC91231_IOMUX_COM_BASE_ADDR) +#define IOMUXSW_AP_MUX_CTL (IOMUX_AP_BASE + 0x000) +#define IOMUXSW_SP_MUX_CTL (IOMUX_COM_BASE + 0x000) +#define IOMUXSW_PAD_CTL (IOMUX_COM_BASE + 0x200) + +#define IOMUXINT_OBS1 (IOMUX_AP_BASE + 0x600) +#define IOMUXINT_OBS2 (IOMUX_AP_BASE + 0x004) + +static DEFINE_SPINLOCK(gpio_mux_lock); + +#define NB_PORTS ((PIN_MAX + 32) / 32) +#define PIN_GLOBAL_NUM(pin) \ + (((pin & MUX_SIDE_MASK) >> MUX_SIDE_SHIFT)*PIN_AP_MAX + \ + ((pin & MUX_REG_MASK) >> MUX_REG_SHIFT)*4 + \ + ((pin & MUX_FIELD_MASK) >> MUX_FIELD_SHIFT)) + +unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG]; +/* + * set the mode for a IOMUX pin. + */ +int mxc_iomux_mode(const unsigned int pin_mode) +{ + u32 side, field, l, mode, ret = 0; + void __iomem *reg; + + side = (pin_mode & MUX_SIDE_MASK) >> MUX_SIDE_SHIFT; + switch (side) { + case MUX_SIDE_AP: + reg = IOMUXSW_AP_MUX_CTL; + break; + case MUX_SIDE_SP: + reg = IOMUXSW_SP_MUX_CTL; + break; + default: + return -EINVAL; + } + reg += ((pin_mode & MUX_REG_MASK) >> MUX_REG_SHIFT) * 4; + field = (pin_mode & MUX_FIELD_MASK) >> MUX_FIELD_SHIFT; + mode = (pin_mode & MUX_MODE_MASK) >> MUX_MODE_SHIFT; + + spin_lock(&gpio_mux_lock); + + l = __raw_readl(reg); + l &= ~(0xff << (field * 8)); + l |= mode << (field * 8); + __raw_writel(l, reg); + + spin_unlock(&gpio_mux_lock); + + return ret; +} +EXPORT_SYMBOL(mxc_iomux_mode); + +/* + * This function configures the pad value for a IOMUX pin. + */ +void mxc_iomux_set_pad(enum iomux_pins pin, u32 config) +{ + u32 padgrp, field, l; + void __iomem *reg; + + padgrp = (pin & MUX_PADGRP_MASK) >> MUX_PADGRP_SHIFT; + reg = IOMUXSW_PAD_CTL + (pin + 2) / 3 * 4; + field = (pin + 2) % 3; + + pr_debug("%s: reg offset = 0x%x, field = %d\n", + __func__, (pin + 2) / 3, field); + + spin_lock(&gpio_mux_lock); + + l = __raw_readl(reg); + l &= ~(0x1ff << (field * 10)); + l |= config << (field * 10); + __raw_writel(l, reg); + + spin_unlock(&gpio_mux_lock); +} +EXPORT_SYMBOL(mxc_iomux_set_pad); + +/* + * allocs a single pin: + * - reserves the pin so that it is not claimed by another driver + * - setups the iomux according to the configuration + */ +int mxc_iomux_alloc_pin(const unsigned int pin_mode, const char *label) +{ + unsigned pad = PIN_GLOBAL_NUM(pin_mode); + if (pad >= (PIN_MAX + 1)) { + printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n", + pad, label ? label : "?"); + return -EINVAL; + } + + if (test_and_set_bit(pad, mxc_pin_alloc_map)) { + printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n", + pad, label ? label : "?"); + return -EBUSY; + } + mxc_iomux_mode(pin_mode); + + return 0; +} +EXPORT_SYMBOL(mxc_iomux_alloc_pin); + +int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count, + const char *label) +{ + unsigned int *p = pin_list; + int i; + int ret = -EINVAL; + + for (i = 0; i < count; i++) { + ret = mxc_iomux_alloc_pin(*p, label); + if (ret) + goto setup_error; + p++; + } + return 0; + +setup_error: + mxc_iomux_release_multiple_pins(pin_list, i); + return ret; +} +EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins); + +void mxc_iomux_release_pin(const unsigned int pin_mode) +{ + unsigned pad = PIN_GLOBAL_NUM(pin_mode); + + if (pad < (PIN_MAX + 1)) + clear_bit(pad, mxc_pin_alloc_map); +} +EXPORT_SYMBOL(mxc_iomux_release_pin); + +void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count) +{ + unsigned int *p = pin_list; + int i; + + for (i = 0; i < count; i++) { + mxc_iomux_release_pin(*p); + p++; + } +} +EXPORT_SYMBOL(mxc_iomux_release_multiple_pins); diff --git a/arch/arm/mach-mxc91231/magx-zn5.c b/arch/arm/mach-mxc91231/magx-zn5.c new file mode 100644 index 000000000000..7dbe4ca12efd --- /dev/null +++ b/arch/arm/mach-mxc91231/magx-zn5.c @@ -0,0 +1,63 @@ +/* + * Copyright 2009 Dmitriy Taychenachev <dimichxp@gmail.com> + * + * This file is released under the GPLv2 or later. + */ + +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/device.h> + +#include <asm/mach-types.h> +#include <asm/mach/time.h> +#include <asm/mach/arch.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/iomux-mxc91231.h> +#include <mach/mmc.h> +#include <mach/imx-uart.h> + +#include "devices.h" + +static struct imxuart_platform_data uart_pdata = { +}; + +static struct imxmmc_platform_data sdhc_pdata = { +}; + +static void __init zn5_init(void) +{ + pm_power_off = mxc91231_power_off; + + mxc_iomux_alloc_pin(MXC91231_PIN_SP_USB_DAT_VP__RXD2, "uart2-rx"); + mxc_iomux_alloc_pin(MXC91231_PIN_SP_USB_SE0_VM__TXD2, "uart2-tx"); + + mxc_register_device(&mxc_uart_device1, &uart_pdata); + mxc_register_device(&mxc_uart_device0, &uart_pdata); + + mxc_register_device(&mxc_sdhc_device0, &sdhc_pdata); + + mxc_register_device(&mxc_wdog_device0, NULL); + + return; +} + +static void __init zn5_timer_init(void) +{ + mxc91231_clocks_init(26000000); /* 26mhz ckih */ +} + +struct sys_timer zn5_timer = { + .init = zn5_timer_init, +}; + +MACHINE_START(MAGX_ZN5, "Motorola Zn5") + .phys_io = MXC91231_AIPS1_BASE_ADDR, + .io_pg_offst = ((MXC91231_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x100, + .map_io = mxc91231_map_io, + .init_irq = mxc91231_init_irq, + .timer = &zn5_timer, + .init_machine = zn5_init, +MACHINE_END diff --git a/arch/arm/mach-mxc91231/mm.c b/arch/arm/mach-mxc91231/mm.c new file mode 100644 index 000000000000..6becda3ff331 --- /dev/null +++ b/arch/arm/mach-mxc91231/mm.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 1999,2000 Arm Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * Copyright (C) 2002 Shane Nay (shane@minirl.com) + * Copyright 2004-2005 Freescale Semiconductor, Inc. All Rights Reserved. + * - add MXC specific definitions + * Copyright 2006 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/mm.h> +#include <linux/init.h> +#include <mach/hardware.h> +#include <mach/common.h> +#include <asm/pgtable.h> +#include <asm/mach/map.h> + +/* + * This structure defines the MXC memory map. + */ +static struct map_desc mxc_io_desc[] __initdata = { + { + .virtual = MXC91231_L2CC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_L2CC_BASE_ADDR), + .length = MXC91231_L2CC_SIZE, + .type = MT_DEVICE, + }, { + .virtual = MXC91231_X_MEMC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_X_MEMC_BASE_ADDR), + .length = MXC91231_X_MEMC_SIZE, + .type = MT_DEVICE, + }, { + .virtual = MXC91231_ROMP_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_ROMP_BASE_ADDR), + .length = MXC91231_ROMP_SIZE, + .type = MT_DEVICE, + }, { + .virtual = MXC91231_AVIC_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_AVIC_BASE_ADDR), + .length = MXC91231_AVIC_SIZE, + .type = MT_DEVICE, + }, { + .virtual = MXC91231_AIPS1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_AIPS1_BASE_ADDR), + .length = MXC91231_AIPS1_SIZE, + .type = MT_DEVICE, + }, { + .virtual = MXC91231_SPBA0_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_SPBA0_BASE_ADDR), + .length = MXC91231_SPBA0_SIZE, + .type = MT_DEVICE, + }, { + .virtual = MXC91231_SPBA1_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_SPBA1_BASE_ADDR), + .length = MXC91231_SPBA1_SIZE, + .type = MT_DEVICE, + }, { + .virtual = MXC91231_AIPS2_BASE_ADDR_VIRT, + .pfn = __phys_to_pfn(MXC91231_AIPS2_BASE_ADDR), + .length = MXC91231_AIPS2_SIZE, + .type = MT_DEVICE, + }, +}; + +/* + * This function initializes the memory map. It is called during the + * system startup to create static physical to virtual memory map for + * the IO modules. + */ +void __init mxc91231_map_io(void) +{ + mxc_set_cpu_type(MXC_CPU_MXC91231); + + iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc)); +} + +void __init mxc91231_init_irq(void) +{ + mxc_init_irq(MXC91231_IO_ADDRESS(MXC91231_AVIC_BASE_ADDR)); +} diff --git a/arch/arm/mach-mxc91231/system.c b/arch/arm/mach-mxc91231/system.c new file mode 100644 index 000000000000..736f7efd874a --- /dev/null +++ b/arch/arm/mach-mxc91231/system.c @@ -0,0 +1,51 @@ +/* + * Copyright 2009 Dmitriy Taychenachev <dimichxp@gmail.com> + * + * This file is released under the GPLv2 or later. + */ + +#include <linux/delay.h> +#include <linux/io.h> + +#include <asm/proc-fns.h> +#include <mach/hardware.h> + +#include "crm_regs.h" + +#define WDOG_WCR MXC91231_IO_ADDRESS(MXC91231_WDOG1_BASE_ADDR) +#define WDOG_WCR_OUT_ENABLE (1 << 6) +#define WDOG_WCR_ASSERT (1 << 5) + +void mxc91231_power_off(void) +{ + u16 wcr; + + wcr = __raw_readw(WDOG_WCR); + wcr |= WDOG_WCR_OUT_ENABLE; + wcr &= ~WDOG_WCR_ASSERT; + __raw_writew(wcr, WDOG_WCR); +} + +void mxc91231_arch_reset(char mode, const char *cmd) +{ + u32 amcr; + + /* Reset the AP using CRM */ + amcr = __raw_readl(MXC_CRMAP_AMCR); + amcr &= ~MXC_CRMAP_AMCR_SW_AP; + __raw_writel(amcr, MXC_CRMAP_AMCR); + + mdelay(10); + cpu_reset(0); +} + +void mxc91231_prepare_idle(void) +{ + u32 crm_ctl; + + /* Go to WAIT mode after WFI */ + crm_ctl = __raw_readl(MXC_DSM_CRM_CONTROL); + crm_ctl &= ~(MXC_DSM_CRM_CTRL_LPMD0 | MXC_DSM_CRM_CTRL_LPMD1); + crm_ctl |= MXC_DSM_CRM_CTRL_LPMD_WAIT_MODE; + __raw_writel(crm_ctl, MXC_DSM_CRM_CONTROL); +} diff --git a/arch/arm/mach-netx/include/mach/entry-macro.S b/arch/arm/mach-netx/include/mach/entry-macro.S index a1952a0feda6..844f1f9acbdf 100644 --- a/arch/arm/mach-netx/include/mach/entry-macro.S +++ b/arch/arm/mach-netx/include/mach/entry-macro.S @@ -24,15 +24,13 @@ .endm .macro get_irqnr_preamble, base, tmp + ldr \base, =io_p2v(0x001ff000) .endm .macro arch_ret_to_user, tmp1, tmp2 .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - mov \base, #io_p2v(0x00100000) - add \base, \base, #0x000ff000 - ldr \irqstat, [\base, #0] clz \irqnr, \irqstat rsb \irqnr, \irqnr, #31 diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig new file mode 100644 index 000000000000..2a02b49c40f0 --- /dev/null +++ b/arch/arm/mach-nomadik/Kconfig @@ -0,0 +1,21 @@ +if ARCH_NOMADIK + +menu "Nomadik boards" + +config MACH_NOMADIK_8815NHK + bool "ST 8815 Nomadik Hardware Kit (evaluation board)" + select NOMADIK_8815 + +endmenu + +config NOMADIK_8815 + bool + + +config I2C_BITBANG_8815NHK + tristate "Driver for bit-bang busses found on the 8815 NHK" + depends on I2C && MACH_NOMADIK_8815NHK + select I2C_ALGOBIT + default y + +endif diff --git a/arch/arm/mach-nomadik/Makefile b/arch/arm/mach-nomadik/Makefile new file mode 100644 index 000000000000..412040982a40 --- /dev/null +++ b/arch/arm/mach-nomadik/Makefile @@ -0,0 +1,19 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +# Object file lists. + +obj-y += clock.o timer.o gpio.o + +# Cpu revision +obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o + +# Specific board support +obj-$(CONFIG_MACH_NOMADIK_8815NHK) += board-nhk8815.o + +# Nomadik extra devices +obj-$(CONFIG_I2C_BITBANG_8815NHK) += i2c-8815nhk.o diff --git a/arch/arm/mach-nomadik/Makefile.boot b/arch/arm/mach-nomadik/Makefile.boot new file mode 100644 index 000000000000..c7e75acfe6c9 --- /dev/null +++ b/arch/arm/mach-nomadik/Makefile.boot @@ -0,0 +1,4 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 + diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c new file mode 100644 index 000000000000..79bdea943eb4 --- /dev/null +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -0,0 +1,111 @@ +/* + * linux/arch/arm/mach-nomadik/board-8815nhk.c + * + * Copyright (C) STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * NHK15 board specifc driver definition + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/amba/bus.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <mach/setup.h> +#include "clock.h" + +#define __MEM_4K_RESOURCE(x) \ + .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} + +static struct amba_device uart0_device = { + .dev = { .init_name = "uart0" }, + __MEM_4K_RESOURCE(NOMADIK_UART0_BASE), + .irq = {IRQ_UART0, NO_IRQ}, +}; + +static struct amba_device uart1_device = { + .dev = { .init_name = "uart1" }, + __MEM_4K_RESOURCE(NOMADIK_UART1_BASE), + .irq = {IRQ_UART1, NO_IRQ}, +}; + +static struct amba_device *amba_devs[] __initdata = { + &uart0_device, + &uart1_device, +}; + +/* We have a fixed clock alone, by now */ +static struct clk nhk8815_clk_48 = { + .rate = 48*1000*1000, +}; + +static struct resource nhk8815_eth_resources[] = { + { + .name = "smc91x-regs", + .start = 0x34000000 + 0x300, + .end = 0x34000000 + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = NOMADIK_GPIO_TO_IRQ(115), + .end = NOMADIK_GPIO_TO_IRQ(115), + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING, + } +}; + +static struct platform_device nhk8815_eth_device = { + .name = "smc91x", + .resource = nhk8815_eth_resources, + .num_resources = ARRAY_SIZE(nhk8815_eth_resources), +}; + +static int __init nhk8815_eth_init(void) +{ + int gpio_nr = 115; /* hardwired in the board */ + int err; + + err = gpio_request(gpio_nr, "eth_irq"); + if (!err) err = nmk_gpio_set_mode(gpio_nr, NMK_GPIO_ALT_GPIO); + if (!err) err = gpio_direction_input(gpio_nr); + if (err) + pr_err("Error %i in %s\n", err, __func__); + return err; +} +device_initcall(nhk8815_eth_init); + +static struct platform_device *nhk8815_platform_devices[] __initdata = { + &nhk8815_eth_device, + /* will add more devices */ +}; + +static void __init nhk8815_platform_init(void) +{ + int i; + + cpu8815_platform_init(); + platform_add_devices(nhk8815_platform_devices, + ARRAY_SIZE(nhk8815_platform_devices)); + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + nmdk_clk_create(&nhk8815_clk_48, amba_devs[i]->dev.init_name); + amba_device_register(amba_devs[i], &iomem_resource); + } +} + +MACHINE_START(NOMADIK, "NHK8815") + /* Maintainer: ST MicroElectronics */ + .phys_io = NOMADIK_UART0_BASE, + .io_pg_offst = (IO_ADDRESS(NOMADIK_UART0_BASE) >> 18) & 0xfffc, + .boot_params = 0x100, + .map_io = cpu8815_map_io, + .init_irq = cpu8815_init_irq, + .timer = &nomadik_timer, + .init_machine = nhk8815_platform_init, +MACHINE_END diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c new file mode 100644 index 000000000000..9f92502a0083 --- /dev/null +++ b/arch/arm/mach-nomadik/clock.c @@ -0,0 +1,45 @@ +/* + * linux/arch/arm/mach-nomadik/clock.c + * + * Copyright (C) 2009 Alessandro Rubini + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/clk.h> +#include <asm/clkdev.h> +#include "clock.h" + +/* + * The nomadik board uses generic clocks, but the serial pl011 file + * calls clk_enable(), clk_disable(), clk_get_rate(), so we provide them + */ +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +/* enable and disable do nothing */ +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +/* Create a clock structure with the given name */ +int nmdk_clk_create(struct clk *clk, const char *dev_id) +{ + struct clk_lookup *clkdev; + + clkdev = clkdev_alloc(clk, NULL, dev_id); + if (!clkdev) + return -ENOMEM; + clkdev_add(clkdev); + return 0; +} diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h new file mode 100644 index 000000000000..235faec7f627 --- /dev/null +++ b/arch/arm/mach-nomadik/clock.h @@ -0,0 +1,14 @@ + +/* + * linux/arch/arm/mach-nomadik/clock.h + * + * Copyright (C) 2009 Alessandro Rubini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +struct clk { + unsigned long rate; +}; +extern int nmdk_clk_create(struct clk *clk, const char *dev_id); diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c new file mode 100644 index 000000000000..f93c59634191 --- /dev/null +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -0,0 +1,139 @@ +/* + * Copyright STMicroelectronics, 2007. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/amba/bus.h> +#include <linux/gpio.h> + +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <asm/mach/map.h> +#include <asm/hardware/vic.h> + +#include <asm/cacheflush.h> +#include <asm/hardware/cache-l2x0.h> + +/* The 8815 has 4 GPIO blocks, let's register them immediately */ +static struct nmk_gpio_platform_data cpu8815_gpio[] = { + { + .name = "GPIO-0-31", + .first_gpio = 0, + .first_irq = NOMADIK_GPIO_TO_IRQ(0), + .parent_irq = IRQ_GPIO0, + }, { + .name = "GPIO-32-63", + .first_gpio = 32, + .first_irq = NOMADIK_GPIO_TO_IRQ(32), + .parent_irq = IRQ_GPIO1, + }, { + .name = "GPIO-64-95", + .first_gpio = 64, + .first_irq = NOMADIK_GPIO_TO_IRQ(64), + .parent_irq = IRQ_GPIO2, + }, { + .name = "GPIO-96-127", /* 124..127 not routed to pin */ + .first_gpio = 96, + .first_irq = NOMADIK_GPIO_TO_IRQ(96), + .parent_irq = IRQ_GPIO3, + } +}; + +#define __MEM_4K_RESOURCE(x) \ + .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} + +static struct amba_device cpu8815_amba_gpio[] = { + { + .dev = { + .init_name = "gpio0", + .platform_data = cpu8815_gpio + 0, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO0_BASE), + }, { + .dev = { + .init_name = "gpio1", + .platform_data = cpu8815_gpio + 1, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO1_BASE), + }, { + .dev = { + .init_name = "gpio2", + .platform_data = cpu8815_gpio + 2, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO2_BASE), + }, { + .dev = { + .init_name = "gpio3", + .platform_data = cpu8815_gpio + 3, + }, + __MEM_4K_RESOURCE(NOMADIK_GPIO3_BASE), + }, +}; + +static struct amba_device *amba_devs[] __initdata = { + cpu8815_amba_gpio + 0, + cpu8815_amba_gpio + 1, + cpu8815_amba_gpio + 2, + cpu8815_amba_gpio + 3, +}; + +static int __init cpu8815_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) + amba_device_register(amba_devs[i], &iomem_resource); + return 0; +} +arch_initcall(cpu8815_init); + +/* All SoC devices live in the same area (see hardware.h) */ +static struct map_desc nomadik_io_desc[] __initdata = { + { + .virtual = NOMADIK_IO_VIRTUAL, + .pfn = __phys_to_pfn(NOMADIK_IO_PHYSICAL), + .length = NOMADIK_IO_SIZE, + .type = MT_DEVICE, + } + /* static ram and secured ram may be added later */ +}; + +void __init cpu8815_map_io(void) +{ + iotable_init(nomadik_io_desc, ARRAY_SIZE(nomadik_io_desc)); +} + +void __init cpu8815_init_irq(void) +{ + /* This modified VIC cell has two register blocks, at 0 and 0x20 */ + vic_init(io_p2v(NOMADIK_IC_BASE + 0x00), IRQ_VIC_START + 0, ~0, 0); + vic_init(io_p2v(NOMADIK_IC_BASE + 0x20), IRQ_VIC_START + 32, ~0, 0); +} + +/* + * This function is called from the board init ("init_machine"). + */ + void __init cpu8815_platform_init(void) +{ +#ifdef CONFIG_CACHE_L2X0 + /* At full speed latency must be >=2, so 0x249 in low bits */ + l2x0_init(io_p2v(NOMADIK_L2CC_BASE), 0x00730249, 0xfe000fff); +#endif + return; +} diff --git a/arch/arm/mach-nomadik/gpio.c b/arch/arm/mach-nomadik/gpio.c new file mode 100644 index 000000000000..9a09b2791e03 --- /dev/null +++ b/arch/arm/mach-nomadik/gpio.c @@ -0,0 +1,396 @@ +/* + * Generic GPIO driver for logic cells found in the Nomadik SoC + * + * Copyright (C) 2008,2009 STMicroelectronics + * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> + * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/amba/bus.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/irq.h> + +#include <mach/hardware.h> +#include <mach/gpio.h> + +/* + * The GPIO module in the Nomadik family of Systems-on-Chip is an + * AMBA device, managing 32 pins and alternate functions. The logic block + * is currently only used in the Nomadik. + * + * Symbols in this file are called "nmk_gpio" for "nomadik gpio" + */ + +#define NMK_GPIO_PER_CHIP 32 +struct nmk_gpio_chip { + struct gpio_chip chip; + void __iomem *addr; + unsigned int parent_irq; + spinlock_t *lock; + /* Keep track of configured edges */ + u32 edge_rising; + u32 edge_falling; +}; + +/* Mode functions */ +int nmk_gpio_set_mode(int gpio, int gpio_mode) +{ + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 afunc, bfunc, bit; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + bit = 1 << (gpio - nmk_chip->chip.base); + + spin_lock_irqsave(&nmk_chip->lock, flags); + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; + if (gpio_mode & NMK_GPIO_ALT_A) + afunc |= bit; + if (gpio_mode & NMK_GPIO_ALT_B) + bfunc |= bit; + writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); + writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; +} +EXPORT_SYMBOL(nmk_gpio_set_mode); + +int nmk_gpio_get_mode(int gpio) +{ + struct nmk_gpio_chip *nmk_chip; + u32 afunc, bfunc, bit; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + bit = 1 << (gpio - nmk_chip->chip.base); + + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; + + return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); +} +EXPORT_SYMBOL(nmk_gpio_get_mode); + + +/* IRQ functions */ +static inline int nmk_gpio_get_bitmask(int gpio) +{ + return 1 << (gpio % 32); +} + +static void nmk_gpio_irq_ack(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + if (!nmk_chip) + return; + writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); +} + +static void nmk_gpio_irq_mask(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask, reg; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return; + + /* we must individually clear the two edges */ + spin_lock_irqsave(&nmk_chip->lock, flags); + if (nmk_chip->edge_rising & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg &= ~bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + } + if (nmk_chip->edge_falling & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg &= ~bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + } + spin_unlock_irqrestore(&nmk_chip->lock, flags); +}; + +static void nmk_gpio_irq_unmask(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask, reg; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return; + + /* we must individually set the two edges */ + spin_lock_irqsave(&nmk_chip->lock, flags); + if (nmk_chip->edge_rising & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg |= bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + } + if (nmk_chip->edge_falling & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg |= bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + } + spin_unlock_irqrestore(&nmk_chip->lock, flags); +} + +static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return -EINVAL; + + if (type & IRQ_TYPE_LEVEL_HIGH) + return -EINVAL; + if (type & IRQ_TYPE_LEVEL_LOW) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); + + nmk_chip->edge_rising &= ~bitmask; + if (type & IRQ_TYPE_EDGE_RISING) + nmk_chip->edge_rising |= bitmask; + writel(nmk_chip->edge_rising, nmk_chip->addr + NMK_GPIO_RIMSC); + + nmk_chip->edge_falling &= ~bitmask; + if (type & IRQ_TYPE_EDGE_FALLING) + nmk_chip->edge_falling |= bitmask; + writel(nmk_chip->edge_falling, nmk_chip->addr + NMK_GPIO_FIMSC); + + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + nmk_gpio_irq_unmask(irq); + + return 0; +} + +static struct irq_chip nmk_gpio_irq_chip = { + .name = "Nomadik-GPIO", + .ack = nmk_gpio_irq_ack, + .mask = nmk_gpio_irq_mask, + .unmask = nmk_gpio_irq_unmask, + .set_type = nmk_gpio_irq_set_type, +}; + +static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct nmk_gpio_chip *nmk_chip; + struct irq_chip *host_chip; + unsigned int gpio_irq; + u32 pending; + unsigned int first_irq; + + nmk_chip = get_irq_data(irq); + first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); + while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { + gpio_irq = first_irq + __ffs(pending); + generic_handle_irq(gpio_irq); + } + if (0) {/* don't ack parent irq, as ack == disable */ + host_chip = get_irq_chip(irq); + host_chip->ack(irq); + } +} + +static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) +{ + unsigned int first_irq; + int i; + + first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); + for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) { + set_irq_chip(i, &nmk_gpio_irq_chip); + set_irq_handler(i, handle_edge_irq); + set_irq_flags(i, IRQF_VALID); + set_irq_chip_data(i, nmk_chip); + } + set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); + set_irq_data(nmk_chip->parent_irq, nmk_chip); + return 0; +} + +/* I/O Functions */ +static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); + return 0; +} + +static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); + return 0; +} + +static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + u32 bit = 1 << offset; + + return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; +} + +static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + u32 bit = 1 << offset; + + if (val) + writel(bit, nmk_chip->addr + NMK_GPIO_DATS); + else + writel(bit, nmk_chip->addr + NMK_GPIO_DATC); +} + +/* This structure is replicated for each GPIO block allocated at probe time */ +static struct gpio_chip nmk_gpio_template = { + .direction_input = nmk_gpio_make_input, + .get = nmk_gpio_get_input, + .direction_output = nmk_gpio_make_output, + .set = nmk_gpio_set_output, + .ngpio = NMK_GPIO_PER_CHIP, + .can_sleep = 0, +}; + +static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) +{ + struct nmk_gpio_platform_data *pdata; + struct nmk_gpio_chip *nmk_chip; + struct gpio_chip *chip; + int ret; + + pdata = dev->dev.platform_data; + ret = amba_request_regions(dev, pdata->name); + if (ret) + return ret; + + nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); + if (!nmk_chip) { + ret = -ENOMEM; + goto out_amba; + } + /* + * The virt address in nmk_chip->addr is in the nomadik register space, + * so we can simply convert the resource address, without remapping + */ + nmk_chip->addr = io_p2v(dev->res.start); + nmk_chip->chip = nmk_gpio_template; + nmk_chip->parent_irq = pdata->parent_irq; + + chip = &nmk_chip->chip; + chip->base = pdata->first_gpio; + chip->label = pdata->name; + chip->dev = &dev->dev; + chip->owner = THIS_MODULE; + + ret = gpiochip_add(&nmk_chip->chip); + if (ret) + goto out_free; + + amba_set_drvdata(dev, nmk_chip); + + nmk_gpio_init_irq(nmk_chip); + + dev_info(&dev->dev, "Bits %i-%i at address %p\n", + nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); + return 0; + + out_free: + kfree(nmk_chip); + out_amba: + amba_release_regions(dev); + dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, + pdata->first_gpio, pdata->first_gpio+31); + return ret; +} + +static int nmk_gpio_remove(struct amba_device *dev) +{ + struct nmk_gpio_chip *nmk_chip; + + nmk_chip = amba_get_drvdata(dev); + gpiochip_remove(&nmk_chip->chip); + kfree(nmk_chip); + amba_release_regions(dev); + return 0; +} + + +/* We have 0x1f080060 and 0x1f180060, accept both using the mask */ +static struct amba_id nmk_gpio_ids[] = { + { + .id = 0x1f080060, + .mask = 0xffefffff, + }, + {0, 0}, +}; + +static struct amba_driver nmk_gpio_driver = { + .drv = { + .owner = THIS_MODULE, + .name = "gpio", + }, + .probe = nmk_gpio_probe, + .remove = nmk_gpio_remove, + .suspend = NULL, /* to be done */ + .resume = NULL, + .id_table = nmk_gpio_ids, +}; + +static int __init nmk_gpio_init(void) +{ + return amba_driver_register(&nmk_gpio_driver); +} + +arch_initcall(nmk_gpio_init); + +MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); +MODULE_DESCRIPTION("Nomadik GPIO Driver"); +MODULE_LICENSE("GPL"); + + diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c new file mode 100644 index 000000000000..abfe25a08d6b --- /dev/null +++ b/arch/arm/mach-nomadik/i2c-8815nhk.c @@ -0,0 +1,65 @@ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/i2c-algo-bit.h> +#include <linux/i2c-gpio.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> + +/* + * There are two busses in the 8815NHK. + * They could, in theory, be driven by the hardware component, but we + * use bit-bang through GPIO by now, to keep things simple + */ + +static struct i2c_gpio_platform_data nhk8815_i2c_data0 = { + /* keep defaults for timeouts; pins are push-pull bidirectional */ + .scl_pin = 62, + .sda_pin = 63, +}; + +static struct i2c_gpio_platform_data nhk8815_i2c_data1 = { + /* keep defaults for timeouts; pins are push-pull bidirectional */ + .scl_pin = 53, + .sda_pin = 54, +}; + +/* first bus: GPIO XX and YY */ +static struct platform_device nhk8815_i2c_dev0 = { + .name = "i2c-gpio", + .id = 0, + .dev = { + .platform_data = &nhk8815_i2c_data0, + }, +}; +/* second bus: GPIO XX and YY */ +static struct platform_device nhk8815_i2c_dev1 = { + .name = "i2c-gpio", + .id = 1, + .dev = { + .platform_data = &nhk8815_i2c_data1, + }, +}; + +static int __init nhk8815_i2c_init(void) +{ + nmk_gpio_set_mode(nhk8815_i2c_data0.scl_pin, NMK_GPIO_ALT_GPIO); + nmk_gpio_set_mode(nhk8815_i2c_data0.sda_pin, NMK_GPIO_ALT_GPIO); + platform_device_register(&nhk8815_i2c_dev0); + + nmk_gpio_set_mode(nhk8815_i2c_data1.scl_pin, NMK_GPIO_ALT_GPIO); + nmk_gpio_set_mode(nhk8815_i2c_data1.sda_pin, NMK_GPIO_ALT_GPIO); + platform_device_register(&nhk8815_i2c_dev1); + + return 0; +} + +static void __exit nhk8815_i2c_exit(void) +{ + platform_device_unregister(&nhk8815_i2c_dev0); + platform_device_unregister(&nhk8815_i2c_dev1); + return; +} + +module_init(nhk8815_i2c_init); +module_exit(nhk8815_i2c_exit); diff --git a/arch/arm/mach-nomadik/include/mach/clkdev.h b/arch/arm/mach-nomadik/include/mach/clkdev.h new file mode 100644 index 000000000000..04b37a89801c --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/debug-macro.S b/arch/arm/mach-nomadik/include/mach/debug-macro.S new file mode 100644 index 000000000000..e876990e1569 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/debug-macro.S @@ -0,0 +1,22 @@ +/* + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x10000000 @ physical base address + movne \rx, #0xf0000000 @ virtual base + add \rx, \rx, #0x00100000 + add \rx, \rx, #0x000fb000 + .endm + +#include <asm/hardware/debug-pl01x.S> diff --git a/arch/arm/mach-nomadik/include/mach/entry-macro.S b/arch/arm/mach-nomadik/include/mach/entry-macro.S new file mode 100644 index 000000000000..49f1aa3bb420 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/entry-macro.S @@ -0,0 +1,43 @@ +/* + * Low-level IRQ helper macros for Nomadik platforms + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <mach/hardware.h> +#include <mach/irqs.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =IO_ADDRESS(NOMADIK_IC_BASE) + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + /* This stanza gets the irq mask from one of two status registers */ + mov \irqnr, #0 + ldr \irqstat, [\base, #VIC_REG_IRQSR0] @ get masked status + cmp \irqstat, #0 + bne 1001f + add \irqnr, \irqnr, #32 + ldr \irqstat, [\base, #VIC_REG_IRQSR1] @ get masked status + +1001: tst \irqstat, #15 + bne 1002f + add \irqnr, \irqnr, #4 + movs \irqstat, \irqstat, lsr #4 + bne 1001b +1002: tst \irqstat, #1 + bne 1003f + add \irqnr, \irqnr, #1 + movs \irqstat, \irqstat, lsr #1 + bne 1002b +1003: /* EQ will be set if no irqs pending */ + .endm diff --git a/arch/arm/mach-nomadik/include/mach/gpio.h b/arch/arm/mach-nomadik/include/mach/gpio.h new file mode 100644 index 000000000000..61577c9f9a7d --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/gpio.h @@ -0,0 +1,71 @@ +/* + * Structures and registers for GPIO access in the Nomadik SoC + * + * Copyright (C) 2008 STMicroelectronics + * Author: Prafulla WADASKAR <prafulla.wadaskar@st.com> + * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#include <asm-generic/gpio.h> + +/* + * These currently cause a function call to happen, they may be optimized + * if needed by adding cpu-specific defines to identify blocks + * (see mach-pxa/include/mach/gpio.h as an example using GPLR etc) + */ +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +extern int nmk_gpio_set_mode(int gpio, int gpio_mode); +extern int nmk_gpio_get_mode(int gpio); + +/* + * Platform data to register a block: only the initial gpio/irq number. + */ +struct nmk_gpio_platform_data { + char *name; + int first_gpio; + int first_irq; + int parent_irq; +}; + +#endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-nomadik/include/mach/hardware.h b/arch/arm/mach-nomadik/include/mach/hardware.h new file mode 100644 index 000000000000..6316dba3bfc8 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/hardware.h @@ -0,0 +1,90 @@ +/* + * This file contains the hardware definitions of the Nomadik. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * YOU should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +/* Nomadik registers live from 0x1000.0000 to 0x1023.0000 -- currently */ +#define NOMADIK_IO_VIRTUAL 0xF0000000 /* VA of IO */ +#define NOMADIK_IO_PHYSICAL 0x10000000 /* PA of IO */ +#define NOMADIK_IO_SIZE 0x00300000 /* 3MB for all regs */ + +/* used in C code, so cast to proper type */ +#define io_p2v(x) ((void __iomem *)(x) \ + - NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL) +#define io_v2p(x) ((unsigned long)(x) \ + - NOMADIK_IO_VIRTUAL + NOMADIK_IO_PHYSICAL) + +/* used in asm code, so no casts */ +#define IO_ADDRESS(x) ((x) - NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL) + +/* + * Base address defination for Nomadik Onchip Logic Block + */ +#define NOMADIK_FSMC_BASE 0x10100000 /* FSMC registers */ +#define NOMADIK_SDRAMC_BASE 0x10110000 /* SDRAM Controller */ +#define NOMADIK_CLCDC_BASE 0x10120000 /* CLCD Controller */ +#define NOMADIK_MDIF_BASE 0x10120000 /* MDIF */ +#define NOMADIK_DMA0_BASE 0x10130000 /* DMA0 Controller */ +#define NOMADIK_IC_BASE 0x10140000 /* Vectored Irq Controller */ +#define NOMADIK_DMA1_BASE 0x10150000 /* DMA1 Controller */ +#define NOMADIK_USB_BASE 0x10170000 /* USB-OTG conf reg base */ +#define NOMADIK_CRYP_BASE 0x10180000 /* Crypto processor */ +#define NOMADIK_SHA1_BASE 0x10190000 /* SHA-1 Processor */ +#define NOMADIK_XTI_BASE 0x101A0000 /* XTI */ +#define NOMADIK_RNG_BASE 0x101B0000 /* Random number generator */ +#define NOMADIK_SRC_BASE 0x101E0000 /* SRC base */ +#define NOMADIK_WDOG_BASE 0x101E1000 /* Watchdog */ +#define NOMADIK_MTU0_BASE 0x101E2000 /* Multiple Timer 0 */ +#define NOMADIK_MTU1_BASE 0x101E3000 /* Multiple Timer 1 */ +#define NOMADIK_GPIO0_BASE 0x101E4000 /* GPIO0 */ +#define NOMADIK_GPIO1_BASE 0x101E5000 /* GPIO1 */ +#define NOMADIK_GPIO2_BASE 0x101E6000 /* GPIO2 */ +#define NOMADIK_GPIO3_BASE 0x101E7000 /* GPIO3 */ +#define NOMADIK_RTC_BASE 0x101E8000 /* Real Time Clock base */ +#define NOMADIK_PMU_BASE 0x101E9000 /* Power Management Unit */ +#define NOMADIK_OWM_BASE 0x101EA000 /* One wire master */ +#define NOMADIK_SCR_BASE 0x101EF000 /* Secure Control registers */ +#define NOMADIK_MSP2_BASE 0x101F0000 /* MSP 2 interface */ +#define NOMADIK_MSP1_BASE 0x101F1000 /* MSP 1 interface */ +#define NOMADIK_UART2_BASE 0x101F2000 /* UART 2 interface */ +#define NOMADIK_SSIRx_BASE 0x101F3000 /* SSI 8-ch rx interface */ +#define NOMADIK_SSITx_BASE 0x101F4000 /* SSI 8-ch tx interface */ +#define NOMADIK_MSHC_BASE 0x101F5000 /* Memory Stick(Pro) Host */ +#define NOMADIK_SDI_BASE 0x101F6000 /* SD-card/MM-Card */ +#define NOMADIK_I2C1_BASE 0x101F7000 /* I2C1 interface */ +#define NOMADIK_I2C0_BASE 0x101F8000 /* I2C0 interface */ +#define NOMADIK_MSP0_BASE 0x101F9000 /* MSP 0 interface */ +#define NOMADIK_FIRDA_BASE 0x101FA000 /* FIrDA interface */ +#define NOMADIK_UART1_BASE 0x101FB000 /* UART 1 interface */ +#define NOMADIK_SSP_BASE 0x101FC000 /* SSP interface */ +#define NOMADIK_UART0_BASE 0x101FD000 /* UART 0 interface */ +#define NOMADIK_SGA_BASE 0x101FE000 /* SGA interface */ +#define NOMADIK_L2CC_BASE 0x10210000 /* L2 Cache controller */ + +/* Other ranges, not for p2v/v2p */ +#define NOMADIK_BACKUP_RAM 0x80010000 +#define NOMADIK_EBROM 0x80000000 /* Embedded boot ROM */ +#define NOMADIK_HAMACV_DMEM_BASE 0xA0100000 /* HAMACV Data Memory Start */ +#define NOMADIK_HAMACV_DMEM_END 0xA01FFFFF /* HAMACV Data Memory End */ +#define NOMADIK_HAMACA_DMEM 0xA0200000 /* HAMACA Data Memory Space */ + +#define NOMADIK_FSMC_VA IO_ADDRESS(NOMADIK_FSMC_BASE) +#define NOMADIK_MTU0_VA IO_ADDRESS(NOMADIK_MTU0_BASE) +#define NOMADIK_MTU1_VA IO_ADDRESS(NOMADIK_MTU1_BASE) + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-nomadik/include/mach/io.h b/arch/arm/mach-nomadik/include/mach/io.h new file mode 100644 index 000000000000..2e1eca1b8243 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/io.h @@ -0,0 +1,22 @@ +/* + * arch/arm/mach-nomadik/include/mach/io.h (copied from mach-sa1100) + * + * Copyright (C) 1997-1999 Russell King + * + * Modifications: + * 06-12-1997 RMK Created. + * 07-04-1999 RMK Major cleanup + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +/* + * We don't actually have real ISA nor PCI buses, but there is so many + * drivers out there that might just work if we fake them... + */ +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/irqs.h b/arch/arm/mach-nomadik/include/mach/irqs.h new file mode 100644 index 000000000000..8faabc560398 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/irqs.h @@ -0,0 +1,82 @@ +/* + * mach-nomadik/include/mach/irqs.h + * + * Copyright (C) ST Microelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#include <mach/hardware.h> + +#define IRQ_VIC_START 0 /* first VIC interrupt is 0 */ + +/* + * Interrupt numbers generic for all Nomadik Chip cuts + */ +#define IRQ_WATCHDOG 0 +#define IRQ_SOFTINT 1 +#define IRQ_CRYPTO 2 +#define IRQ_OWM 3 +#define IRQ_MTU0 4 +#define IRQ_MTU1 5 +#define IRQ_GPIO0 6 +#define IRQ_GPIO1 7 +#define IRQ_GPIO2 8 +#define IRQ_GPIO3 9 +#define IRQ_RTC_RTT 10 +#define IRQ_SSP 11 +#define IRQ_UART0 12 +#define IRQ_DMA1 13 +#define IRQ_CLCD_MDIF 14 +#define IRQ_DMA0 15 +#define IRQ_PWRFAIL 16 +#define IRQ_UART1 17 +#define IRQ_FIRDA 18 +#define IRQ_MSP0 19 +#define IRQ_I2C0 20 +#define IRQ_I2C1 21 +#define IRQ_SDMMC 22 +#define IRQ_USBOTG 23 +#define IRQ_SVA_IT0 24 +#define IRQ_SVA_IT1 25 +#define IRQ_SAA_IT0 26 +#define IRQ_SAA_IT1 27 +#define IRQ_UART2 28 +#define IRQ_MSP2 31 +#define IRQ_L2CC 48 +#define IRQ_HPI 49 +#define IRQ_SKE 50 +#define IRQ_KP 51 +#define IRQ_MEMST 54 +#define IRQ_SGA_IT 58 +#define IRQ_USBM 60 +#define IRQ_MSP1 62 + +#define NOMADIK_SOC_NR_IRQS 64 + +/* After chip-specific IRQ numbers we have the GPIO ones */ +#define NOMADIK_NR_GPIO 128 /* last 4 not wired to pins */ +#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + NOMADIK_SOC_NR_IRQS) +#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - NOMADIK_SOC_NR_IRQS) +#define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) + +/* Following two are used by entry_macro.S, to access our dual-vic */ +#define VIC_REG_IRQSR0 0 +#define VIC_REG_IRQSR1 0x20 + +#endif /* __ASM_ARCH_IRQS_H */ + diff --git a/arch/arm/mach-nomadik/include/mach/memory.h b/arch/arm/mach-nomadik/include/mach/memory.h new file mode 100644 index 000000000000..1e5689d98ecd --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/memory.h @@ -0,0 +1,28 @@ +/* + * mach-nomadik/include/mach/memory.h + * + * Copyright (C) 1999 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* + * Physical DRAM offset. + */ +#define PHYS_OFFSET UL(0x00000000) + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/mtu.h b/arch/arm/mach-nomadik/include/mach/mtu.h new file mode 100644 index 000000000000..76da7f085330 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/mtu.h @@ -0,0 +1,45 @@ +#ifndef __ASM_ARCH_MTU_H +#define __ASM_ARCH_MTU_H + +/* + * The MTU device hosts four different counters, with 4 set of + * registers. These are register names. + */ + +#define MTU_IMSC 0x00 /* Interrupt mask set/clear */ +#define MTU_RIS 0x04 /* Raw interrupt status */ +#define MTU_MIS 0x08 /* Masked interrupt status */ +#define MTU_ICR 0x0C /* Interrupt clear register */ + +/* per-timer registers take 0..3 as argument */ +#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */ +#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */ +#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */ +#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */ + +/* bits for the control register */ +#define MTU_CRn_ENA 0x80 +#define MTU_CRn_PERIODIC 0x40 /* if 0 = free-running */ +#define MTU_CRn_PRESCALE_MASK 0x0c +#define MTU_CRn_PRESCALE_1 0x00 +#define MTU_CRn_PRESCALE_16 0x04 +#define MTU_CRn_PRESCALE_256 0x08 +#define MTU_CRn_32BITS 0x02 +#define MTU_CRn_ONESHOT 0x01 /* if 0 = wraps reloading from BGLR*/ + +/* Other registers are usual amba/primecell registers, currently not used */ +#define MTU_ITCR 0xff0 +#define MTU_ITOP 0xff4 + +#define MTU_PERIPH_ID0 0xfe0 +#define MTU_PERIPH_ID1 0xfe4 +#define MTU_PERIPH_ID2 0xfe8 +#define MTU_PERIPH_ID3 0xfeC + +#define MTU_PCELL0 0xff0 +#define MTU_PCELL1 0xff4 +#define MTU_PCELL2 0xff8 +#define MTU_PCELL3 0xffC + +#endif /* __ASM_ARCH_MTU_H */ + diff --git a/arch/arm/mach-nomadik/include/mach/setup.h b/arch/arm/mach-nomadik/include/mach/setup.h new file mode 100644 index 000000000000..a4e468cf63da --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/setup.h @@ -0,0 +1,22 @@ + +/* + * These symbols are needed for board-specific files to call their + * own cpu-specific files + */ + +#ifndef __ASM_ARCH_SETUP_H +#define __ASM_ARCH_SETUP_H + +#include <asm/mach/time.h> +#include <linux/init.h> + +#ifdef CONFIG_NOMADIK_8815 + +extern void cpu8815_map_io(void); +extern void cpu8815_platform_init(void); +extern void cpu8815_init_irq(void); +extern struct sys_timer nomadik_timer; + +#endif /* NOMADIK_8815 */ + +#endif /* __ASM_ARCH_SETUP_H */ diff --git a/arch/arm/mach-nomadik/include/mach/system.h b/arch/arm/mach-nomadik/include/mach/system.h new file mode 100644 index 000000000000..7119f688116e --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/system.h @@ -0,0 +1,45 @@ +/* + * mach-nomadik/include/mach/system.h + * + * Copyright (C) 2008 STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include <linux/io.h> +#include <mach/hardware.h> + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ + void __iomem *src_rstsr = io_p2v(NOMADIK_SRC_BASE + 0x18); + + /* FIXME: use egpio when implemented */ + + /* Write anything to Reset status register */ + writel(1, src_rstsr); +} + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/timex.h b/arch/arm/mach-nomadik/include/mach/timex.h new file mode 100644 index 000000000000..318b8896ce96 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/timex.h @@ -0,0 +1,6 @@ +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +#define CLOCK_TICK_RATE 2400000 + +#endif diff --git a/arch/arm/mach-nomadik/include/mach/uncompress.h b/arch/arm/mach-nomadik/include/mach/uncompress.h new file mode 100644 index 000000000000..071003bc8456 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/uncompress.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include <asm/setup.h> +#include <asm/io.h> +#include <mach/hardware.h> + +/* we need the constants in amba/serial.h, but it refers to amba_device */ +struct amba_device; +#include <linux/amba/serial.h> + +#define NOMADIK_UART_DR 0x101FB000 +#define NOMADIK_UART_LCRH 0x101FB02c +#define NOMADIK_UART_CR 0x101FB030 +#define NOMADIK_UART_FR 0x101FB018 + +static void putc(const char c) +{ + /* Do nothing if the UART is not enabled. */ + if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN)) + return; + + if (c == '\n') + putc('\r'); + + while (readb(NOMADIK_UART_FR) & UART01x_FR_TXFF) + barrier(); + writeb(c, NOMADIK_UART_DR); +} + +static void flush(void) +{ + if (!(readb(NOMADIK_UART_CR) & UART01x_CR_UARTEN)) + return; + while (readb(NOMADIK_UART_FR) & UART01x_FR_BUSY) + barrier(); +} + +static inline void arch_decomp_setup(void) +{ +} + +#define arch_decomp_wdog() /* nothing to do here */ + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-nomadik/include/mach/vmalloc.h b/arch/arm/mach-nomadik/include/mach/vmalloc.h new file mode 100644 index 000000000000..be12e31ea528 --- /dev/null +++ b/arch/arm/mach-nomadik/include/mach/vmalloc.h @@ -0,0 +1,2 @@ + +#define VMALLOC_END 0xe8000000 diff --git a/arch/arm/mach-nomadik/timer.c b/arch/arm/mach-nomadik/timer.c new file mode 100644 index 000000000000..d1738e7061d4 --- /dev/null +++ b/arch/arm/mach-nomadik/timer.c @@ -0,0 +1,164 @@ +/* + * linux/arch/arm/mach-nomadik/timer.c + * + * Copyright (C) 2008 STMicroelectronics + * Copyright (C) 2009 Alessandro Rubini, somewhat based on at91sam926x + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + */ +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/clockchips.h> +#include <linux/jiffies.h> +#include <asm/mach/time.h> +#include <mach/mtu.h> + +#define TIMER_CTRL 0x80 /* No divisor */ +#define TIMER_PERIODIC 0x40 +#define TIMER_SZ32BIT 0x02 + +/* Initial value for SRC control register: all timers use MXTAL/8 source */ +#define SRC_CR_INIT_MASK 0x00007fff +#define SRC_CR_INIT_VAL 0x2aaa8000 + +static u32 nmdk_count; /* accumulated count */ +static u32 nmdk_cycle; /* write-once */ +static __iomem void *mtu_base; + +/* + * clocksource: the MTU device is a decrementing counters, so we negate + * the value being read. + */ +static cycle_t nmdk_read_timer(struct clocksource *cs) +{ + u32 count = readl(mtu_base + MTU_VAL(0)); + return nmdk_count + nmdk_cycle - count; + +} + +static struct clocksource nmdk_clksrc = { + .name = "mtu_0", + .rating = 120, + .read = nmdk_read_timer, + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +/* + * Clockevent device: currently only periodic mode is supported + */ +static void nmdk_clkevt_mode(enum clock_event_mode mode, + struct clock_event_device *dev) +{ + unsigned long flags; + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + /* enable interrupts -- and count current value? */ + raw_local_irq_save(flags); + writel(readl(mtu_base + MTU_IMSC) | 1, mtu_base + MTU_IMSC); + raw_local_irq_restore(flags); + break; + case CLOCK_EVT_MODE_ONESHOT: + BUG(); /* Not supported, yet */ + /* FALLTHROUGH */ + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + /* disable irq */ + raw_local_irq_save(flags); + writel(readl(mtu_base + MTU_IMSC) & ~1, mtu_base + MTU_IMSC); + raw_local_irq_restore(flags); + break; + case CLOCK_EVT_MODE_RESUME: + break; + } +} + +static struct clock_event_device nmdk_clkevt = { + .name = "mtu_0", + .features = CLOCK_EVT_FEAT_PERIODIC, + .shift = 32, + .rating = 100, + .set_mode = nmdk_clkevt_mode, +}; + +/* + * IRQ Handler for the timer 0 of the MTU block. The irq is not shared + * as we are the only users of mtu0 by now. + */ +static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id) +{ + /* ack: "interrupt clear register" */ + writel( 1 << 0, mtu_base + MTU_ICR); + + /* we can't count lost ticks, unfortunately */ + nmdk_count += nmdk_cycle; + nmdk_clkevt.event_handler(&nmdk_clkevt); + + return IRQ_HANDLED; +} + +/* + * Set up timer interrupt, and return the current time in seconds. + */ +static struct irqaction nmdk_timer_irq = { + .name = "Nomadik Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = nmdk_timer_interrupt, +}; + +static void nmdk_timer_reset(void) +{ + u32 cr; + + writel(0, mtu_base + MTU_CR(0)); /* off */ + + /* configure load and background-load, and fire it up */ + writel(nmdk_cycle, mtu_base + MTU_LR(0)); + writel(nmdk_cycle, mtu_base + MTU_BGLR(0)); + cr = MTU_CRn_PERIODIC | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS; + writel(cr, mtu_base + MTU_CR(0)); + writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); +} + +static void __init nmdk_timer_init(void) +{ + u32 src_cr; + unsigned long rate; + int bits; + + rate = CLOCK_TICK_RATE; /* 2.4MHz */ + nmdk_cycle = (rate + HZ/2) / HZ; + + /* Configure timer sources in "system reset controller" ctrl reg */ + src_cr = readl(io_p2v(NOMADIK_SRC_BASE)); + src_cr &= SRC_CR_INIT_MASK; + src_cr |= SRC_CR_INIT_VAL; + writel(src_cr, io_p2v(NOMADIK_SRC_BASE)); + + /* Save global pointer to mtu, used by functions above */ + mtu_base = io_p2v(NOMADIK_MTU0_BASE); + + /* Init the timer and register clocksource */ + nmdk_timer_reset(); + + nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift); + bits = 8*sizeof(nmdk_count); + nmdk_clksrc.mask = CLOCKSOURCE_MASK(bits); + + clocksource_register(&nmdk_clksrc); + + /* Register irq and clockevents */ + setup_irq(IRQ_MTU0, &nmdk_timer_irq); + nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift); + nmdk_clkevt.cpumask = cpumask_of(0); + clockevents_register_device(&nmdk_clkevt); +} + +struct sys_timer nomadik_timer = { + .init = nmdk_timer_init, +}; diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 57e477bd89c6..7e1e721f0324 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -39,7 +39,7 @@ static struct platform_device *sdp4430_devices[] __initdata = { }; static struct omap_uart_config sdp4430_uart_config __initdata = { - .enabled_uarts = (1 << 0) | (1 << 1) | (1 << 2), + .enabled_uarts = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3), }; static struct omap_lcd_config sdp4430_lcd_config __initdata = { diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index dff5528fbfb5..e26af837510b 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -51,6 +51,7 @@ #define OVERO_GPIO_BT_XGATE 15 #define OVERO_GPIO_W2W_NRESET 16 +#define OVERO_GPIO_PENDOWN 114 #define OVERO_GPIO_BT_NRESET 164 #define OVERO_GPIO_USBH_CPEN 168 #define OVERO_GPIO_USBH_NRESET 183 diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index 1d3c93bf86d3..f3c91a1ca391 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -29,9 +29,9 @@ * These registers appear once per CM module. */ -#define OMAP3430_CM_REVISION OMAP_CM_REGADDR(OCP_MOD, 0x0000) -#define OMAP3430_CM_SYSCONFIG OMAP_CM_REGADDR(OCP_MOD, 0x0010) -#define OMAP3430_CM_POLCTRL OMAP_CM_REGADDR(OCP_MOD, 0x009c) +#define OMAP3430_CM_REVISION OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000) +#define OMAP3430_CM_SYSCONFIG OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010) +#define OMAP3430_CM_POLCTRL OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c) #define OMAP3_CM_CLKOUT_CTRL_OFFSET 0x0070 #define OMAP3430_CM_CLKOUT_CTRL OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 99b6e1546311..d7288f1dc64f 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -168,6 +168,42 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { #define OMAP34XX_MCBSP_PDATA_SZ 0 #endif +static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = { + { + .phys_base = OMAP44XX_MCBSP1_BASE, + .dma_rx_sync = OMAP44XX_DMA_MCBSP1_RX, + .dma_tx_sync = OMAP44XX_DMA_MCBSP1_TX, + .rx_irq = INT_24XX_MCBSP1_IRQ_RX, + .tx_irq = INT_24XX_MCBSP1_IRQ_TX, + .ops = &omap2_mcbsp_ops, + }, + { + .phys_base = OMAP44XX_MCBSP2_BASE, + .dma_rx_sync = OMAP44XX_DMA_MCBSP2_RX, + .dma_tx_sync = OMAP44XX_DMA_MCBSP2_TX, + .rx_irq = INT_24XX_MCBSP2_IRQ_RX, + .tx_irq = INT_24XX_MCBSP2_IRQ_TX, + .ops = &omap2_mcbsp_ops, + }, + { + .phys_base = OMAP44XX_MCBSP3_BASE, + .dma_rx_sync = OMAP44XX_DMA_MCBSP3_RX, + .dma_tx_sync = OMAP44XX_DMA_MCBSP3_TX, + .rx_irq = INT_24XX_MCBSP3_IRQ_RX, + .tx_irq = INT_24XX_MCBSP3_IRQ_TX, + .ops = &omap2_mcbsp_ops, + }, + { + .phys_base = OMAP44XX_MCBSP4_BASE, + .dma_rx_sync = OMAP44XX_DMA_MCBSP4_RX, + .dma_tx_sync = OMAP44XX_DMA_MCBSP4_TX, + .rx_irq = INT_24XX_MCBSP4_IRQ_RX, + .tx_irq = INT_24XX_MCBSP4_IRQ_TX, + .ops = &omap2_mcbsp_ops, + }, +}; +#define OMAP44XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap44xx_mcbsp_pdata) + static int __init omap2_mcbsp_init(void) { if (cpu_is_omap2420()) @@ -176,6 +212,8 @@ static int __init omap2_mcbsp_init(void) omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ; if (cpu_is_omap34xx()) omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ; + if (cpu_is_omap44xx()) + omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ; mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *), GFP_KERNEL); @@ -191,6 +229,9 @@ static int __init omap2_mcbsp_init(void) if (cpu_is_omap34xx()) omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata, OMAP34XX_MCBSP_PDATA_SZ); + if (cpu_is_omap44xx()) + omap_mcbsp_register_board_cfg(omap44xx_mcbsp_pdata, + OMAP44XX_MCBSP_PDATA_SZ); return omap_mcbsp_init(); } diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index f7b3baf76678..21201cd4117b 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -11,9 +11,6 @@ #ifndef __ARCH_ARM_MACH_OMAP2_PM_H #define __ARCH_ARM_MACH_OMAP2_PM_H -extern int omap2_pm_init(void); -extern int omap3_pm_init(void); - #ifdef CONFIG_PM_DEBUG extern void omap2_pm_dump(int mode, int resume, unsigned int us); extern int omap2_pm_debug; diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index db1025562fb0..528dbdc26e23 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -470,7 +470,7 @@ static void __init prcm_setup_regs(void) WKUP_MOD, PM_WKEN); } -int __init omap2_pm_init(void) +static int __init omap2_pm_init(void) { u32 l; diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 841d4c5ed8be..488d595d8e4b 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -39,7 +39,9 @@ struct power_state { struct powerdomain *pwrdm; u32 next_state; +#ifdef CONFIG_SUSPEND u32 saved_state; +#endif struct list_head node; }; @@ -293,6 +295,9 @@ out: local_irq_enable(); } +#ifdef CONFIG_SUSPEND +static suspend_state_t suspend_state; + static int omap3_pm_prepare(void) { disable_hlt(); @@ -321,7 +326,6 @@ static int omap3_pm_suspend(void) restore: /* Restore next_pwrsts */ list_for_each_entry(pwrst, &pwrst_list, node) { - set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); state = pwrdm_read_prev_pwrst(pwrst->pwrdm); if (state > pwrst->next_state) { printk(KERN_INFO "Powerdomain (%s) didn't enter " @@ -329,6 +333,7 @@ restore: pwrst->pwrdm->name, pwrst->next_state); ret = -1; } + set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); } if (ret) printk(KERN_ERR "Could not enter target state in pm_suspend\n"); @@ -339,11 +344,11 @@ restore: return ret; } -static int omap3_pm_enter(suspend_state_t state) +static int omap3_pm_enter(suspend_state_t unused) { int ret = 0; - switch (state) { + switch (suspend_state) { case PM_SUSPEND_STANDBY: case PM_SUSPEND_MEM: ret = omap3_pm_suspend(); @@ -360,12 +365,30 @@ static void omap3_pm_finish(void) enable_hlt(); } +/* Hooks to enable / disable UART interrupts during suspend */ +static int omap3_pm_begin(suspend_state_t state) +{ + suspend_state = state; + omap_uart_enable_irqs(0); + return 0; +} + +static void omap3_pm_end(void) +{ + suspend_state = PM_SUSPEND_ON; + omap_uart_enable_irqs(1); + return; +} + static struct platform_suspend_ops omap_pm_ops = { + .begin = omap3_pm_begin, + .end = omap3_pm_end, .prepare = omap3_pm_prepare, .enter = omap3_pm_enter, .finish = omap3_pm_finish, .valid = suspend_valid_only_mem, }; +#endif /* CONFIG_SUSPEND */ /** @@ -613,6 +636,24 @@ static void __init prcm_setup_regs(void) /* Clear any pending PRCM interrupts */ prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + /* Don't attach IVA interrupts */ + prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL); + prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1); + prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3); + prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL); + + /* Clear any pending 'reset' flags */ + prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST); + prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST); + prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST); + prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST); + prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST); + prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST); + prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST); + + /* Clear any pending PRCM interrupts */ + prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + omap3_iva_idle(); omap3_d2d_idle(); } @@ -652,7 +693,7 @@ static int __init clkdms_setup(struct clockdomain *clkdm) return 0; } -int __init omap3_pm_init(void) +static int __init omap3_pm_init(void) { struct power_state *pwrst, *tmp; int ret; @@ -692,7 +733,9 @@ int __init omap3_pm_init(void) _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend, omap34xx_cpu_suspend_sz); +#ifdef CONFIG_SUSPEND suspend_set_ops(&omap_pm_ops); +#endif /* CONFIG_SUSPEND */ pm_idle = omap3_pm_idle; diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index b094c15bfe47..ce22344b94e7 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -54,6 +54,7 @@ struct omap_uart_state { struct plat_serial8250_port *p; struct list_head node; + struct platform_device pdev; #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) int context_valid; @@ -68,10 +69,9 @@ struct omap_uart_state { #endif }; -static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS]; static LIST_HEAD(uart_list); -static struct plat_serial8250_port serial_platform_data[] = { +static struct plat_serial8250_port serial_platform_data0[] = { { .membase = IO_ADDRESS(OMAP_UART1_BASE), .mapbase = OMAP_UART1_BASE, @@ -81,6 +81,12 @@ static struct plat_serial8250_port serial_platform_data[] = { .regshift = 2, .uartclk = OMAP24XX_BASE_BAUD * 16, }, { + .flags = 0 + } +}; + +static struct plat_serial8250_port serial_platform_data1[] = { + { .membase = IO_ADDRESS(OMAP_UART2_BASE), .mapbase = OMAP_UART2_BASE, .irq = 73, @@ -89,6 +95,12 @@ static struct plat_serial8250_port serial_platform_data[] = { .regshift = 2, .uartclk = OMAP24XX_BASE_BAUD * 16, }, { + .flags = 0 + } +}; + +static struct plat_serial8250_port serial_platform_data2[] = { + { .membase = IO_ADDRESS(OMAP_UART3_BASE), .mapbase = OMAP_UART3_BASE, .irq = 74, @@ -97,6 +109,16 @@ static struct plat_serial8250_port serial_platform_data[] = { .regshift = 2, .uartclk = OMAP24XX_BASE_BAUD * 16, }, { +#ifdef CONFIG_ARCH_OMAP4 + .membase = IO_ADDRESS(OMAP_UART4_BASE), + .mapbase = OMAP_UART4_BASE, + .irq = 70, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = OMAP24XX_BASE_BAUD * 16, + }, { +#endif .flags = 0 } }; @@ -217,6 +239,40 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart) clk_disable(uart->fck); } +static void omap_uart_enable_wakeup(struct omap_uart_state *uart) +{ + /* Set wake-enable bit */ + if (uart->wk_en && uart->wk_mask) { + u32 v = __raw_readl(uart->wk_en); + v |= uart->wk_mask; + __raw_writel(v, uart->wk_en); + } + + /* Ensure IOPAD wake-enables are set */ + if (cpu_is_omap34xx() && uart->padconf) { + u16 v = omap_ctrl_readw(uart->padconf); + v |= OMAP3_PADCONF_WAKEUPENABLE0; + omap_ctrl_writew(v, uart->padconf); + } +} + +static void omap_uart_disable_wakeup(struct omap_uart_state *uart) +{ + /* Clear wake-enable bit */ + if (uart->wk_en && uart->wk_mask) { + u32 v = __raw_readl(uart->wk_en); + v &= ~uart->wk_mask; + __raw_writel(v, uart->wk_en); + } + + /* Ensure IOPAD wake-enables are cleared */ + if (cpu_is_omap34xx() && uart->padconf) { + u16 v = omap_ctrl_readw(uart->padconf); + v &= ~OMAP3_PADCONF_WAKEUPENABLE0; + omap_ctrl_writew(v, uart->padconf); + } +} + static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, int enable) { @@ -246,6 +302,11 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart) static void omap_uart_allow_sleep(struct omap_uart_state *uart) { + if (device_may_wakeup(&uart->pdev.dev)) + omap_uart_enable_wakeup(uart); + else + omap_uart_disable_wakeup(uart); + if (!uart->clocked) return; @@ -292,7 +353,6 @@ void omap_uart_resume_idle(int num) /* Check for normal UART wakeup */ if (__raw_readl(uart->wk_st) & uart->wk_mask) omap_uart_block_sleep(uart); - return; } } @@ -346,16 +406,13 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) return IRQ_NONE; } -static u32 sleep_timeout = DEFAULT_TIMEOUT; - static void omap_uart_idle_init(struct omap_uart_state *uart) { - u32 v; struct plat_serial8250_port *p = uart->p; int ret; uart->can_sleep = 0; - uart->timeout = sleep_timeout; + uart->timeout = DEFAULT_TIMEOUT; setup_timer(&uart->timer, omap_uart_idle_timer, (unsigned long) uart); mod_timer(&uart->timer, jiffies + uart->timeout); @@ -413,76 +470,101 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) uart->padconf = 0; } - /* Set wake-enable bit */ - if (uart->wk_en && uart->wk_mask) { - v = __raw_readl(uart->wk_en); - v |= uart->wk_mask; - __raw_writel(v, uart->wk_en); - } - - /* Ensure IOPAD wake-enables are set */ - if (cpu_is_omap34xx() && uart->padconf) { - u16 v; - - v = omap_ctrl_readw(uart->padconf); - v |= OMAP3_PADCONF_WAKEUPENABLE0; - omap_ctrl_writew(v, uart->padconf); - } - p->flags |= UPF_SHARE_IRQ; ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, "serial idle", (void *)uart); WARN_ON(ret); } -static ssize_t sleep_timeout_show(struct kobject *kobj, - struct kobj_attribute *attr, +void omap_uart_enable_irqs(int enable) +{ + int ret; + struct omap_uart_state *uart; + + list_for_each_entry(uart, &uart_list, node) { + if (enable) + ret = request_irq(uart->p->irq, omap_uart_interrupt, + IRQF_SHARED, "serial idle", (void *)uart); + else + free_irq(uart->p->irq, (void *)uart); + } +} + +static ssize_t sleep_timeout_show(struct device *dev, + struct device_attribute *attr, char *buf) { - return sprintf(buf, "%u\n", sleep_timeout / HZ); + struct platform_device *pdev = container_of(dev, + struct platform_device, dev); + struct omap_uart_state *uart = container_of(pdev, + struct omap_uart_state, pdev); + + return sprintf(buf, "%u\n", uart->timeout / HZ); } -static ssize_t sleep_timeout_store(struct kobject *kobj, - struct kobj_attribute *attr, +static ssize_t sleep_timeout_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t n) { - struct omap_uart_state *uart; + struct platform_device *pdev = container_of(dev, + struct platform_device, dev); + struct omap_uart_state *uart = container_of(pdev, + struct omap_uart_state, pdev); unsigned int value; if (sscanf(buf, "%u", &value) != 1) { printk(KERN_ERR "sleep_timeout_store: Invalid value\n"); return -EINVAL; } - sleep_timeout = value * HZ; - list_for_each_entry(uart, &uart_list, node) { - uart->timeout = sleep_timeout; - if (uart->timeout) - mod_timer(&uart->timer, jiffies + uart->timeout); - else - /* A zero value means disable timeout feature */ - omap_uart_block_sleep(uart); - } + + uart->timeout = value * HZ; + if (uart->timeout) + mod_timer(&uart->timer, jiffies + uart->timeout); + else + /* A zero value means disable timeout feature */ + omap_uart_block_sleep(uart); + return n; } -static struct kobj_attribute sleep_timeout_attr = - __ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store); - +DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store); +#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr)) #else static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} +#define DEV_CREATE_FILE(dev, attr) #endif /* CONFIG_PM */ -static struct platform_device serial_device = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = serial_platform_data, +static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = { + { + .pdev = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = serial_platform_data0, + }, + }, + }, { + .pdev = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM1, + .dev = { + .platform_data = serial_platform_data1, + }, + }, + }, { + .pdev = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM2, + .dev = { + .platform_data = serial_platform_data2, + }, + }, }, }; void __init omap_serial_init(void) { - int i, err; + int i; const struct omap_uart_config *info; char name[16]; @@ -496,14 +578,12 @@ void __init omap_serial_init(void) if (info == NULL) return; - if (cpu_is_omap44xx()) { - for (i = 0; i < OMAP_MAX_NR_PORTS; i++) - serial_platform_data[i].irq += 32; - } for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { - struct plat_serial8250_port *p = serial_platform_data + i; struct omap_uart_state *uart = &omap_uart[i]; + struct platform_device *pdev = &uart->pdev; + struct device *dev = &pdev->dev; + struct plat_serial8250_port *p = dev->platform_data; if (!(info->enabled_uarts & (1 << i))) { p->membase = NULL; @@ -531,20 +611,21 @@ void __init omap_serial_init(void) uart->num = i; p->private_data = uart; uart->p = p; - list_add(&uart->node, &uart_list); + list_add_tail(&uart->node, &uart_list); + + if (cpu_is_omap44xx()) + p->irq += 32; omap_uart_enable_clocks(uart); omap_uart_reset(uart); omap_uart_idle_init(uart); - } - - err = platform_device_register(&serial_device); - -#ifdef CONFIG_PM - if (!err) - err = sysfs_create_file(&serial_device.dev.kobj, - &sleep_timeout_attr.attr); -#endif + if (WARN_ON(platform_device_register(pdev))) + continue; + if ((cpu_is_omap34xx() && uart->padconf) || + (uart->wk_en && uart->wk_mask)) { + device_init_wakeup(dev, true); + DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout); + } + } } - diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig index 2c7035d8dcbf..c3d513cad5ac 100644 --- a/arch/arm/mach-orion5x/Kconfig +++ b/arch/arm/mach-orion5x/Kconfig @@ -89,6 +89,27 @@ config MACH_EDMINI_V2 Say 'Y' here if you want your kernel to support the LaCie Ethernet Disk mini V2. +config MACH_D2NET + bool "LaCie d2 Network" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + LaCie d2 Network NAS. + +config MACH_BIGDISK + bool "LaCie Big Disk Network" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + LaCie Big Disk Network NAS. + +config MACH_NET2BIG + bool "LaCie 2Big Network" + select I2C_BOARDINFO + help + Say 'Y' here if you want your kernel to support the + LaCie 2Big Network NAS. + config MACH_MSS2 bool "Maxtor Shared Storage II" help diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile index edc38e2c856f..89772fcd65c7 100644 --- a/arch/arm/mach-orion5x/Makefile +++ b/arch/arm/mach-orion5x/Makefile @@ -12,6 +12,9 @@ obj-$(CONFIG_MACH_WRT350N_V2) += wrt350n-v2-setup.o obj-$(CONFIG_MACH_TS78XX) += ts78xx-setup.o obj-$(CONFIG_MACH_MV2120) += mv2120-setup.o obj-$(CONFIG_MACH_EDMINI_V2) += edmini_v2-setup.o +obj-$(CONFIG_MACH_D2NET) += d2net-setup.o +obj-$(CONFIG_MACH_BIGDISK) += d2net-setup.o +obj-$(CONFIG_MACH_NET2BIG) += net2big-setup.o obj-$(CONFIG_MACH_MSS2) += mss2-setup.o obj-$(CONFIG_MACH_WNR854T) += wnr854t-setup.o obj-$(CONFIG_MACH_RD88F5181L_GE) += rd88f5181l-ge-setup.o diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c index d78731edebb6..1a5d6a0e2602 100644 --- a/arch/arm/mach-orion5x/addr-map.c +++ b/arch/arm/mach-orion5x/addr-map.c @@ -84,7 +84,8 @@ static int __init orion5x_cpu_win_can_remap(int win) orion5x_pcie_id(&dev, &rev); if ((dev == MV88F5281_DEV_ID && win < 4) || (dev == MV88F5182_DEV_ID && win < 2) - || (dev == MV88F5181_DEV_ID && win < 2)) + || (dev == MV88F5181_DEV_ID && win < 2) + || (dev == MV88F6183_DEV_ID && win < 4)) return 1; return 0; diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c new file mode 100644 index 000000000000..9d4bf763f25b --- /dev/null +++ b/arch/arm/mach-orion5x/d2net-setup.c @@ -0,0 +1,365 @@ +/* + * arch/arm/mach-orion5x/d2net-setup.c + * + * LaCie d2Network and Big Disk Network NAS setup + * + * Copyright (C) 2009 Simon Guinot <sguinot@lacie.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/leds.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <linux/ata_platform.h> +#include <linux/gpio.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/pci.h> +#include <mach/orion5x.h> +#include "common.h" +#include "mpp.h" + +/***************************************************************************** + * LaCie d2 Network Info + ****************************************************************************/ + +/* + * 512KB NOR flash Device bus boot chip select + */ + +#define D2NET_NOR_BOOT_BASE 0xfff80000 +#define D2NET_NOR_BOOT_SIZE SZ_512K + +/***************************************************************************** + * 512KB NOR Flash on Boot Device + ****************************************************************************/ + +/* + * TODO: Check write support on flash MX29LV400CBTC-70G + */ + +static struct mtd_partition d2net_partitions[] = { + { + .name = "Full512kb", + .size = MTDPART_SIZ_FULL, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data d2net_nor_flash_data = { + .width = 1, + .parts = d2net_partitions, + .nr_parts = ARRAY_SIZE(d2net_partitions), +}; + +static struct resource d2net_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = D2NET_NOR_BOOT_BASE, + .end = D2NET_NOR_BOOT_BASE + + D2NET_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device d2net_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &d2net_nor_flash_data, + }, + .num_resources = 1, + .resource = &d2net_nor_flash_resource, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data d2net_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/***************************************************************************** + * I2C devices + ****************************************************************************/ + +/* + * i2c addr | chip | description + * 0x32 | Ricoh 5C372b | RTC + * 0x3e | GMT G762 | PWM fan controller + * 0x50 | HT24LC08 | eeprom (1kB) + * + * TODO: Add G762 support to the g760a driver. + */ +static struct i2c_board_info __initdata d2net_i2c_devices[] = { + { + I2C_BOARD_INFO("rs5c372b", 0x32), + }, { + I2C_BOARD_INFO("24c08", 0x50), + }, +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ + +static struct mv_sata_platform_data d2net_sata_data = { + .n_ports = 2, +}; + +#define D2NET_GPIO_SATA0_POWER 3 +#define D2NET_GPIO_SATA1_POWER 12 + +static void __init d2net_sata_power_init(void) +{ + int err; + + err = gpio_request(D2NET_GPIO_SATA0_POWER, "SATA0 power"); + if (err == 0) { + err = gpio_direction_output(D2NET_GPIO_SATA0_POWER, 1); + if (err) + gpio_free(D2NET_GPIO_SATA0_POWER); + } + if (err) + pr_err("d2net: failed to configure SATA0 power GPIO\n"); + + err = gpio_request(D2NET_GPIO_SATA1_POWER, "SATA1 power"); + if (err == 0) { + err = gpio_direction_output(D2NET_GPIO_SATA1_POWER, 1); + if (err) + gpio_free(D2NET_GPIO_SATA1_POWER); + } + if (err) + pr_err("d2net: failed to configure SATA1 power GPIO\n"); +} + +/***************************************************************************** + * GPIO LED's + ****************************************************************************/ + +/* + * The blue front LED is wired to the CPLD and can blink in relation with the + * SATA activity. This feature is disabled to make this LED compatible with + * the leds-gpio driver: MPP14 and MPP15 are configured to act like output + * GPIO's and have to stay in an active state. This is needed to set the blue + * LED in a "fix on" state regardless of the SATA activity. + * + * The following array detail the different LED registers and the combination + * of their possible values: + * + * led_off | blink_ctrl | SATA active | LED state + * | | | + * 1 | x | x | off + * 0 | 0 | 0 | off + * 0 | 1 | 0 | blink (rate 300ms) + * 0 | x | 1 | on + * + * Notes: The blue and the red front LED's can't be on at the same time. + * Red LED have priority. + */ + +#define D2NET_GPIO_RED_LED 6 +#define D2NET_GPIO_BLUE_LED_BLINK_CTRL 16 +#define D2NET_GPIO_BLUE_LED_OFF 23 +#define D2NET_GPIO_SATA0_ACT 14 +#define D2NET_GPIO_SATA1_ACT 15 + +static struct gpio_led d2net_leds[] = { + { + .name = "d2net:blue:power", + .gpio = D2NET_GPIO_BLUE_LED_OFF, + .active_low = 1, + }, + { + .name = "d2net:red:fail", + .gpio = D2NET_GPIO_RED_LED, + }, +}; + +static struct gpio_led_platform_data d2net_led_data = { + .num_leds = ARRAY_SIZE(d2net_leds), + .leds = d2net_leds, +}; + +static struct platform_device d2net_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &d2net_led_data, + }, +}; + +static void __init d2net_gpio_leds_init(void) +{ + /* Configure GPIO over MPP max number. */ + orion_gpio_set_valid(D2NET_GPIO_BLUE_LED_OFF, 1); + + if (gpio_request(D2NET_GPIO_SATA0_ACT, "LED SATA0 activity") != 0) + return; + if (gpio_direction_output(D2NET_GPIO_SATA0_ACT, 1) != 0) + goto err_free_1; + if (gpio_request(D2NET_GPIO_SATA1_ACT, "LED SATA1 activity") != 0) + goto err_free_1; + if (gpio_direction_output(D2NET_GPIO_SATA1_ACT, 1) != 0) + goto err_free_2; + platform_device_register(&d2net_gpio_leds); + return; + +err_free_2: + gpio_free(D2NET_GPIO_SATA1_ACT); +err_free_1: + gpio_free(D2NET_GPIO_SATA0_ACT); + return; +} + +/**************************************************************************** + * GPIO keys + ****************************************************************************/ + +#define D2NET_GPIO_PUSH_BUTTON 18 +#define D2NET_GPIO_POWER_SWITCH_ON 8 +#define D2NET_GPIO_POWER_SWITCH_OFF 9 + +#define D2NET_SWITCH_POWER_ON 0x1 +#define D2NET_SWITCH_POWER_OFF 0x2 + +static struct gpio_keys_button d2net_buttons[] = { + { + .type = EV_SW, + .code = D2NET_SWITCH_POWER_OFF, + .gpio = D2NET_GPIO_POWER_SWITCH_OFF, + .desc = "Power rocker switch (auto|off)", + .active_low = 0, + }, + { + .type = EV_SW, + .code = D2NET_SWITCH_POWER_ON, + .gpio = D2NET_GPIO_POWER_SWITCH_ON, + .desc = "Power rocker switch (on|auto)", + .active_low = 0, + }, + { + .type = EV_KEY, + .code = KEY_POWER, + .gpio = D2NET_GPIO_PUSH_BUTTON, + .desc = "Front Push Button", + .active_low = 0, + }, +}; + +static struct gpio_keys_platform_data d2net_button_data = { + .buttons = d2net_buttons, + .nbuttons = ARRAY_SIZE(d2net_buttons), +}; + +static struct platform_device d2net_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &d2net_button_data, + }, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static struct orion5x_mpp_mode d2net_mpp_modes[] __initdata = { + { 0, MPP_GPIO }, /* Board ID (bit 0) */ + { 1, MPP_GPIO }, /* Board ID (bit 1) */ + { 2, MPP_GPIO }, /* Board ID (bit 2) */ + { 3, MPP_GPIO }, /* SATA 0 power */ + { 4, MPP_UNUSED }, + { 5, MPP_GPIO }, /* Fan fail detection */ + { 6, MPP_GPIO }, /* Red front LED */ + { 7, MPP_UNUSED }, + { 8, MPP_GPIO }, /* Rear power switch (on|auto) */ + { 9, MPP_GPIO }, /* Rear power switch (auto|off) */ + { 10, MPP_UNUSED }, + { 11, MPP_UNUSED }, + { 12, MPP_GPIO }, /* SATA 1 power */ + { 13, MPP_UNUSED }, + { 14, MPP_GPIO }, /* SATA 0 active */ + { 15, MPP_GPIO }, /* SATA 1 active */ + { 16, MPP_GPIO }, /* Blue front LED blink control */ + { 17, MPP_UNUSED }, + { 18, MPP_GPIO }, /* Front button (0 = Released, 1 = Pushed ) */ + { 19, MPP_UNUSED }, + { -1 } + /* 22: USB port 1 fuse (0 = Fail, 1 = Ok) */ + /* 23: Blue front LED off */ + /* 24: Inhibit board power off (0 = Disabled, 1 = Enabled) */ +}; + +static void __init d2net_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(d2net_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_eth_init(&d2net_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + + d2net_sata_power_init(); + orion5x_sata_init(&d2net_sata_data); + + orion5x_setup_dev_boot_win(D2NET_NOR_BOOT_BASE, + D2NET_NOR_BOOT_SIZE); + platform_device_register(&d2net_nor_flash); + + platform_device_register(&d2net_gpio_buttons); + + d2net_gpio_leds_init(); + + pr_notice("d2net: Flash write are not yet supported.\n"); + + i2c_register_board_info(0, d2net_i2c_devices, + ARRAY_SIZE(d2net_i2c_devices)); +} + +/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */ + +#ifdef CONFIG_MACH_D2NET +MACHINE_START(D2NET, "LaCie d2 Network") + .phys_io = ORION5X_REGS_PHYS_BASE, + .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = d2net_init, + .map_io = orion5x_map_io, + .init_irq = orion5x_init_irq, + .timer = &orion5x_timer, + .fixup = tag_fixup_mem32, +MACHINE_END +#endif + +#ifdef CONFIG_MACH_BIGDISK +MACHINE_START(BIGDISK, "LaCie Big Disk Network") + .phys_io = ORION5X_REGS_PHYS_BASE, + .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = d2net_init, + .map_io = orion5x_map_io, + .init_irq = orion5x_init_irq, + .timer = &orion5x_timer, + .fixup = tag_fixup_mem32, +MACHINE_END +#endif + diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c new file mode 100644 index 000000000000..7bd6283476f9 --- /dev/null +++ b/arch/arm/mach-orion5x/net2big-setup.c @@ -0,0 +1,431 @@ +/* + * arch/arm/mach-orion5x/net2big-setup.c + * + * LaCie 2Big Network NAS setup + * + * Copyright (C) 2009 Simon Guinot <sguinot@lacie.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/physmap.h> +#include <linux/mv643xx_eth.h> +#include <linux/leds.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/i2c.h> +#include <linux/ata_platform.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <mach/orion5x.h> +#include "common.h" +#include "mpp.h" + +/***************************************************************************** + * LaCie 2Big Network Info + ****************************************************************************/ + +/* + * 512KB NOR flash Device bus boot chip select + */ + +#define NET2BIG_NOR_BOOT_BASE 0xfff80000 +#define NET2BIG_NOR_BOOT_SIZE SZ_512K + +/***************************************************************************** + * 512KB NOR Flash on Boot Device + ****************************************************************************/ + +/* + * TODO: Check write support on flash MX29LV400CBTC-70G + */ + +static struct mtd_partition net2big_partitions[] = { + { + .name = "Full512kb", + .size = MTDPART_SIZ_FULL, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data net2big_nor_flash_data = { + .width = 1, + .parts = net2big_partitions, + .nr_parts = ARRAY_SIZE(net2big_partitions), +}; + +static struct resource net2big_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = NET2BIG_NOR_BOOT_BASE, + .end = NET2BIG_NOR_BOOT_BASE + + NET2BIG_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device net2big_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &net2big_nor_flash_data, + }, + .num_resources = 1, + .resource = &net2big_nor_flash_resource, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data net2big_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/***************************************************************************** + * I2C devices + ****************************************************************************/ + +/* + * i2c addr | chip | description + * 0x32 | Ricoh 5C372b | RTC + * 0x50 | HT24LC08 | eeprom (1kB) + */ +static struct i2c_board_info __initdata net2big_i2c_devices[] = { + { + I2C_BOARD_INFO("rs5c372b", 0x32), + }, { + I2C_BOARD_INFO("24c08", 0x50), + }, +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ + +static struct mv_sata_platform_data net2big_sata_data = { + .n_ports = 2, +}; + +#define NET2BIG_GPIO_SATA_POWER_REQ 19 +#define NET2BIG_GPIO_SATA0_POWER 23 +#define NET2BIG_GPIO_SATA1_POWER 25 + +static void __init net2big_sata_power_init(void) +{ + int err; + + /* Configure GPIOs over MPP max number. */ + orion_gpio_set_valid(NET2BIG_GPIO_SATA0_POWER, 1); + orion_gpio_set_valid(NET2BIG_GPIO_SATA1_POWER, 1); + + err = gpio_request(NET2BIG_GPIO_SATA0_POWER, "SATA0 power status"); + if (err == 0) { + err = gpio_direction_input(NET2BIG_GPIO_SATA0_POWER); + if (err) + gpio_free(NET2BIG_GPIO_SATA0_POWER); + } + if (err) { + pr_err("net2big: failed to setup SATA0 power GPIO\n"); + return; + } + + err = gpio_request(NET2BIG_GPIO_SATA1_POWER, "SATA1 power status"); + if (err == 0) { + err = gpio_direction_input(NET2BIG_GPIO_SATA1_POWER); + if (err) + gpio_free(NET2BIG_GPIO_SATA1_POWER); + } + if (err) { + pr_err("net2big: failed to setup SATA1 power GPIO\n"); + goto err_free_1; + } + + err = gpio_request(NET2BIG_GPIO_SATA_POWER_REQ, "SATA power request"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_SATA_POWER_REQ, 0); + if (err) + gpio_free(NET2BIG_GPIO_SATA_POWER_REQ); + } + if (err) { + pr_err("net2big: failed to setup SATA power request GPIO\n"); + goto err_free_2; + } + + if (gpio_get_value(NET2BIG_GPIO_SATA0_POWER) && + gpio_get_value(NET2BIG_GPIO_SATA1_POWER)) { + return; + } + + /* + * SATA power up on both disk is done by pulling high the CPLD power + * request line. The 300ms delay is related to the CPLD clock and is + * needed to be sure that the CPLD has take into account the low line + * status. + */ + msleep(300); + gpio_set_value(NET2BIG_GPIO_SATA_POWER_REQ, 1); + pr_info("net2big: power up SATA hard disks\n"); + + return; + +err_free_2: + gpio_free(NET2BIG_GPIO_SATA1_POWER); +err_free_1: + gpio_free(NET2BIG_GPIO_SATA0_POWER); + + return; +} + +/***************************************************************************** + * GPIO LEDs + ****************************************************************************/ + +/* + * The power front LEDs (blue and red) and SATA red LEDs are controlled via a + * single GPIO line and are compatible with the leds-gpio driver. + * + * The SATA blue LEDs have some hardware blink capabilities which are detailled + * in the following array: + * + * SATAx blue LED | SATAx activity | LED state + * | | + * 0 | 0 | blink (rate 300ms) + * 1 | 0 | off + * ? | 1 | on + * + * Notes: The blue and the red front LED's can't be on at the same time. + * Blue LED have priority. + */ + +#define NET2BIG_GPIO_PWR_RED_LED 6 +#define NET2BIG_GPIO_PWR_BLUE_LED 16 +#define NET2BIG_GPIO_PWR_LED_BLINK_STOP 7 + +#define NET2BIG_GPIO_SATA0_RED_LED 11 +#define NET2BIG_GPIO_SATA1_RED_LED 10 + +#define NET2BIG_GPIO_SATA0_BLUE_LED 17 +#define NET2BIG_GPIO_SATA1_BLUE_LED 13 + +static struct gpio_led net2big_leds[] = { + { + .name = "net2big:red:power", + .gpio = NET2BIG_GPIO_PWR_RED_LED, + }, + { + .name = "net2big:blue:power", + .gpio = NET2BIG_GPIO_PWR_BLUE_LED, + }, + { + .name = "net2big:red:sata0", + .gpio = NET2BIG_GPIO_SATA0_RED_LED, + }, + { + .name = "net2big:red:sata1", + .gpio = NET2BIG_GPIO_SATA1_RED_LED, + }, +}; + +static struct gpio_led_platform_data net2big_led_data = { + .num_leds = ARRAY_SIZE(net2big_leds), + .leds = net2big_leds, +}; + +static struct platform_device net2big_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &net2big_led_data, + }, +}; + +static void __init net2big_gpio_leds_init(void) +{ + int err; + + /* Stop initial CPLD slow red/blue blinking on power LED. */ + err = gpio_request(NET2BIG_GPIO_PWR_LED_BLINK_STOP, + "Power LED blink stop"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_PWR_LED_BLINK_STOP, 1); + if (err) + gpio_free(NET2BIG_GPIO_PWR_LED_BLINK_STOP); + } + if (err) + pr_err("net2big: failed to setup power LED blink GPIO\n"); + + /* + * Configure SATA0 and SATA1 blue LEDs to blink in relation with the + * hard disk activity. + */ + err = gpio_request(NET2BIG_GPIO_SATA0_BLUE_LED, + "SATA0 blue LED control"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_SATA0_BLUE_LED, 1); + if (err) + gpio_free(NET2BIG_GPIO_SATA0_BLUE_LED); + } + if (err) + pr_err("net2big: failed to setup SATA0 blue LED GPIO\n"); + + err = gpio_request(NET2BIG_GPIO_SATA1_BLUE_LED, + "SATA1 blue LED control"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_SATA1_BLUE_LED, 1); + if (err) + gpio_free(NET2BIG_GPIO_SATA1_BLUE_LED); + } + if (err) + pr_err("net2big: failed to setup SATA1 blue LED GPIO\n"); + + platform_device_register(&net2big_gpio_leds); +} + +/**************************************************************************** + * GPIO keys + ****************************************************************************/ + +#define NET2BIG_GPIO_PUSH_BUTTON 18 +#define NET2BIG_GPIO_POWER_SWITCH_ON 8 +#define NET2BIG_GPIO_POWER_SWITCH_OFF 9 + +#define NET2BIG_SWITCH_POWER_ON 0x1 +#define NET2BIG_SWITCH_POWER_OFF 0x2 + +static struct gpio_keys_button net2big_buttons[] = { + { + .type = EV_SW, + .code = NET2BIG_SWITCH_POWER_OFF, + .gpio = NET2BIG_GPIO_POWER_SWITCH_OFF, + .desc = "Power rocker switch (auto|off)", + .active_low = 0, + }, + { + .type = EV_SW, + .code = NET2BIG_SWITCH_POWER_ON, + .gpio = NET2BIG_GPIO_POWER_SWITCH_ON, + .desc = "Power rocker switch (on|auto)", + .active_low = 0, + }, + { + .type = EV_KEY, + .code = KEY_POWER, + .gpio = NET2BIG_GPIO_PUSH_BUTTON, + .desc = "Front Push Button", + .active_low = 0, + }, +}; + +static struct gpio_keys_platform_data net2big_button_data = { + .buttons = net2big_buttons, + .nbuttons = ARRAY_SIZE(net2big_buttons), +}; + +static struct platform_device net2big_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &net2big_button_data, + }, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static struct orion5x_mpp_mode net2big_mpp_modes[] __initdata = { + { 0, MPP_GPIO }, /* Raid mode (bit 0) */ + { 1, MPP_GPIO }, /* USB port 2 fuse (0 = Fail, 1 = Ok) */ + { 2, MPP_GPIO }, /* Raid mode (bit 1) */ + { 3, MPP_GPIO }, /* Board ID (bit 0) */ + { 4, MPP_GPIO }, /* Fan activity (0 = Off, 1 = On) */ + { 5, MPP_GPIO }, /* Fan fail detection */ + { 6, MPP_GPIO }, /* Red front LED (0 = Off, 1 = On) */ + { 7, MPP_GPIO }, /* Disable initial blinking on front LED */ + { 8, MPP_GPIO }, /* Rear power switch (on|auto) */ + { 9, MPP_GPIO }, /* Rear power switch (auto|off) */ + { 10, MPP_GPIO }, /* SATA 1 red LED (0 = Off, 1 = On) */ + { 11, MPP_GPIO }, /* SATA 0 red LED (0 = Off, 1 = On) */ + { 12, MPP_GPIO }, /* Board ID (bit 1) */ + { 13, MPP_GPIO }, /* SATA 1 blue LED blink control */ + { 14, MPP_SATA_LED }, + { 15, MPP_SATA_LED }, + { 16, MPP_GPIO }, /* Blue front LED control */ + { 17, MPP_GPIO }, /* SATA 0 blue LED blink control */ + { 18, MPP_GPIO }, /* Front button (0 = Released, 1 = Pushed ) */ + { 19, MPP_GPIO }, /* SATA{0,1} power On/Off request */ + { -1 } + /* 22: USB port 1 fuse (0 = Fail, 1 = Ok) */ + /* 23: SATA 0 power status */ + /* 24: Board power off */ + /* 25: SATA 1 power status */ +}; + +#define NET2BIG_GPIO_POWER_OFF 24 + +static void net2big_power_off(void) +{ + gpio_set_value(NET2BIG_GPIO_POWER_OFF, 1); +} + +static void __init net2big_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(net2big_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_ehci1_init(); + orion5x_eth_init(&net2big_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + orion5x_xor_init(); + + net2big_sata_power_init(); + orion5x_sata_init(&net2big_sata_data); + + orion5x_setup_dev_boot_win(NET2BIG_NOR_BOOT_BASE, + NET2BIG_NOR_BOOT_SIZE); + platform_device_register(&net2big_nor_flash); + + platform_device_register(&net2big_gpio_buttons); + net2big_gpio_leds_init(); + + i2c_register_board_info(0, net2big_i2c_devices, + ARRAY_SIZE(net2big_i2c_devices)); + + orion_gpio_set_valid(NET2BIG_GPIO_POWER_OFF, 1); + + if (gpio_request(NET2BIG_GPIO_POWER_OFF, "power-off") == 0 && + gpio_direction_output(NET2BIG_GPIO_POWER_OFF, 0) == 0) + pm_power_off = net2big_power_off; + else + pr_err("net2big: failed to configure power-off GPIO\n"); + + pr_notice("net2big: Flash writing is not yet supported.\n"); +} + +/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */ +MACHINE_START(NET2BIG, "LaCie 2Big Network") + .phys_io = ORION5X_REGS_PHYS_BASE, + .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, + .boot_params = 0x00000100, + .init_machine = net2big_init, + .map_io = orion5x_map_io, + .init_irq = orion5x_init_irq, + .timer = &orion5x_timer, + .fixup = tag_fixup_mem32, +MACHINE_END + diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h index ae8441192ef0..7139e0dc26d1 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa300.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa300.h @@ -567,9 +567,9 @@ #define GPIO37_ULPI_DATA_OUT_7 MFP_CFG(GPIO37, AF3) #define GPIO33_ULPI_OTG_INTR MFP_CFG(GPIO33, AF1) -#define ULPI_DIR MFP_CFG_DRV(ULPI_DIR, MFP_AF0, MFP_DS01X) -#define ULPI_NXT MFP_CFG_DRV(ULPI_NXT, MFP_AF0, MFP_DS01X) -#define ULPI_STP MFP_CFG_DRV(ULPI_STP, MFP_AF0, MFP_DS01X) +#define ULPI_DIR MFP_CFG_DRV(ULPI_DIR, AF0, DS01X) +#define ULPI_NXT MFP_CFG_DRV(ULPI_NXT, AF0, DS01X) +#define ULPI_STP MFP_CFG_DRV(ULPI_STP, AF0, DS01X) #endif /* CONFIG_CPU_PXA310 */ #endif /* __ASM_ARCH_MFP_PXA300_H */ diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 6f678d93bf4e..09b7b1a10cad 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -250,7 +250,7 @@ static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0); static struct clk_lookup pxa3xx_clkregs[] = { INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"), /* Power I2C clock is always on */ - INIT_CLKREG(&clk_dummy, "pxa2xx-i2c.1", NULL), + INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL), INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL), INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"), INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"), diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index d4cfa2145386..dfc9b0bc6eb2 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -75,7 +75,7 @@ config MACH_REALVIEW_PBX config REALVIEW_HIGH_PHYS_OFFSET bool "High physical base address for the RealView platform" - depends on !MACH_REALVIEW_PB1176 + depends on MMU && !MACH_REALVIEW_PB1176 default y help RealView boards other than PB1176 have the RAM available at diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index ab615e78b798..dc3519c50ab2 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -208,8 +208,7 @@ struct platform_device realview_i2c_device = { static struct i2c_board_info realview_i2c_board_info[] = { { - I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1), - .type = "ds1338", + I2C_BOARD_INFO("ds1338", 0xd0 >> 1), }, }; diff --git a/arch/arm/mach-realview/include/mach/hardware.h b/arch/arm/mach-realview/include/mach/hardware.h index b42c14f89acb..8a638d15797f 100644 --- a/arch/arm/mach-realview/include/mach/hardware.h +++ b/arch/arm/mach-realview/include/mach/hardware.h @@ -25,6 +25,7 @@ #include <asm/sizes.h> /* macro to get at IO space when running virtually */ +#ifdef CONFIG_MMU /* * Statically mapped addresses: * @@ -33,6 +34,9 @@ * 1fxx xxxx -> fexx xxxx */ #define IO_ADDRESS(x) (((x) & 0x03ffffff) + 0xfb000000) +#else +#define IO_ADDRESS(x) (x) +#endif #define __io_address(n) __io(IO_ADDRESS(n)) #endif diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c index ac0e83f1cc3a..a88458b4799d 100644 --- a/arch/arm/mach-realview/platsmp.c +++ b/arch/arm/mach-realview/platsmp.c @@ -20,6 +20,7 @@ #include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/localtimer.h> +#include <asm/unified.h> #include <mach/board-eb.h> #include <mach/board-pb11mp.h> @@ -137,26 +138,19 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) static void __init poke_milo(void) { - extern void secondary_startup(void); - /* nobody is to be released from the pen yet */ pen_release = -1; /* - * write the address of secondary startup into the system-wide - * flags register, then clear the bottom two bits, which is what - * BootMonitor is waiting for + * Write the address of secondary startup into the system-wide flags + * register. The BootMonitor waits for this register to become + * non-zero. */ -#if 1 #define REALVIEW_SYS_FLAGSS_OFFSET 0x30 - __raw_writel(virt_to_phys(realview_secondary_startup), - __io_address(REALVIEW_SYS_BASE) + - REALVIEW_SYS_FLAGSS_OFFSET); #define REALVIEW_SYS_FLAGSC_OFFSET 0x34 - __raw_writel(3, + __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)), __io_address(REALVIEW_SYS_BASE) + - REALVIEW_SYS_FLAGSC_OFFSET); -#endif + REALVIEW_SYS_FLAGSS_OFFSET); mb(); } diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 41bb65d5b91f..d8c023d4df30 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -12,6 +12,7 @@ config CPU_S3C2410 select S3C2410_GPIO select CPU_LLSERIAL_S3C2410 select S3C2410_PM if PM + select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX help Support for S3C2410 and S3C2410A family from the S3C24XX line of Samsung Mobile CPUs. @@ -45,6 +46,22 @@ config MACH_BAST_IDE Internal node for machines with an BAST style IDE interface +# cpu frequency scaling support + +config S3C2410_CPUFREQ + bool + depends on CPU_FREQ_S3C24XX && CPU_S3C2410 + select S3C2410_CPUFREQ_UTILS + help + CPU Frequency scaling support for S3C2410 + +config S3C2410_PLLTABLE + bool + depends on S3C2410_CPUFREQ && CPU_FREQ_S3C24XX_PLL + default y + help + Select the PLL table for the S3C2410 + menu "S3C2410 Machines" config ARCH_SMDK2410 @@ -79,6 +96,7 @@ config MACH_N30 config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" select CPU_S3C2410 + select S3C2410_IOTIMING if S3C2410_CPUFREQ select PM_SIMTEC if PM select SIMTEC_NOR select MACH_BAST_IDE diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index fca02f82711c..2ab5ba4b266f 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile @@ -15,6 +15,8 @@ obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o obj-$(CONFIG_S3C2410_GPIO) += gpio.o +obj-$(CONFIG_S3C2410_CPUFREQ) += cpu-freq.o +obj-$(CONFIG_S3C2410_PLLTABLE) += pll.o # Machine support diff --git a/arch/arm/mach-s3c2410/cpu-freq.c b/arch/arm/mach-s3c2410/cpu-freq.c new file mode 100644 index 000000000000..9d1186877d08 --- /dev/null +++ b/arch/arm/mach-s3c2410/cpu-freq.c @@ -0,0 +1,159 @@ +/* linux/arch/arm/mach-s3c2410/cpu-freq.c + * + * Copyright (c) 2006,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2410 CPU Frequency scaling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/sysdev.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <mach/regs-clock.h> + +#include <plat/cpu.h> +#include <plat/clock.h> +#include <plat/cpu-freq-core.h> + +/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */ + +static void s3c2410_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) +{ + u32 clkdiv = 0; + + if (cfg->divs.h_divisor == 2) + clkdiv |= S3C2410_CLKDIVN_HDIVN; + + if (cfg->divs.p_divisor != cfg->divs.h_divisor) + clkdiv |= S3C2410_CLKDIVN_PDIVN; + + __raw_writel(clkdiv, S3C2410_CLKDIVN); +} + +static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) +{ + unsigned long hclk, fclk, pclk; + unsigned int hdiv, pdiv; + unsigned long hclk_max; + + fclk = cfg->freq.fclk; + hclk_max = cfg->max.hclk; + + cfg->freq.armclk = fclk; + + s3c_freq_dbg("%s: fclk is %lu, max hclk %lu\n", + __func__, fclk, hclk_max); + + hdiv = (fclk > cfg->max.hclk) ? 2 : 1; + hclk = fclk / hdiv; + + if (hclk > cfg->max.hclk) { + s3c_freq_dbg("%s: hclk too big\n", __func__); + return -EINVAL; + } + + pdiv = (hclk > cfg->max.pclk) ? 2 : 1; + pclk = hclk / pdiv; + + if (pclk > cfg->max.pclk) { + s3c_freq_dbg("%s: pclk too big\n", __func__); + return -EINVAL; + } + + pdiv *= hdiv; + + /* record the result */ + cfg->divs.p_divisor = pdiv; + cfg->divs.h_divisor = hdiv; + + return 0 ; +} + +static struct s3c_cpufreq_info s3c2410_cpufreq_info = { + .max = { + .fclk = 200000000, + .hclk = 100000000, + .pclk = 50000000, + }, + + /* transition latency is about 5ms worst-case, so + * set 10ms to be sure */ + .latency = 10000000, + + .locktime_m = 150, + .locktime_u = 150, + .locktime_bits = 12, + + .need_pll = 1, + + .name = "s3c2410", + .calc_iotiming = s3c2410_iotiming_calc, + .set_iotiming = s3c2410_iotiming_set, + .get_iotiming = s3c2410_iotiming_get, + .resume_clocks = s3c2410_setup_clocks, + + .set_fvco = s3c2410_set_fvco, + .set_refresh = s3c2410_cpufreq_setrefresh, + .set_divs = s3c2410_cpufreq_setdivs, + .calc_divs = s3c2410_cpufreq_calcdivs, + + .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs), +}; + +static int s3c2410_cpufreq_add(struct sys_device *sysdev) +{ + return s3c_cpufreq_register(&s3c2410_cpufreq_info); +} + +static struct sysdev_driver s3c2410_cpufreq_driver = { + .add = s3c2410_cpufreq_add, +}; + +static int __init s3c2410_cpufreq_init(void) +{ + return sysdev_driver_register(&s3c2410_sysclass, + &s3c2410_cpufreq_driver); +} + +arch_initcall(s3c2410_cpufreq_init); + +static int s3c2410a_cpufreq_add(struct sys_device *sysdev) +{ + /* alter the maximum freq settings for S3C2410A. If a board knows + * it only has a maximum of 200, then it should register its own + * limits. */ + + s3c2410_cpufreq_info.max.fclk = 266000000; + s3c2410_cpufreq_info.max.hclk = 133000000; + s3c2410_cpufreq_info.max.pclk = 66500000; + s3c2410_cpufreq_info.name = "s3c2410a"; + + return s3c2410_cpufreq_add(sysdev); +} + +static struct sysdev_driver s3c2410a_cpufreq_driver = { + .add = s3c2410a_cpufreq_add, +}; + +static int __init s3c2410a_cpufreq_init(void) +{ + return sysdev_driver_register(&s3c2410a_sysclass, + &s3c2410a_cpufreq_driver); +} + +arch_initcall(s3c2410a_cpufreq_init); diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index dbf96e60d992..63b753f56c64 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -164,6 +164,17 @@ static int __init s3c2410_dma_drvinit(void) } arch_initcall(s3c2410_dma_drvinit); + +static struct sysdev_driver s3c2410a_dma_driver = { + .add = s3c2410_dma_add, +}; + +static int __init s3c2410a_dma_drvinit(void) +{ + return sysdev_driver_register(&s3c2410a_sysclass, &s3c2410a_dma_driver); +} + +arch_initcall(s3c2410a_dma_drvinit); #endif #if defined(CONFIG_CPU_S3C2442) diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-core.h b/arch/arm/mach-s3c2410/include/mach/gpio-core.h index 8fe192081d3a..f8b879a7973c 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-core.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-core.h @@ -28,7 +28,7 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin) return NULL; chip = &s3c24xx_gpios[pin/32]; - return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL; + return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL; } #endif /* __ASM_ARCH_GPIO_CORE_H */ diff --git a/arch/arm/mach-s3c2410/include/mach/irqs.h b/arch/arm/mach-s3c2410/include/mach/irqs.h index 2a2384ffa7b1..6c12c6312ad8 100644 --- a/arch/arm/mach-s3c2410/include/mach/irqs.h +++ b/arch/arm/mach-s3c2410/include/mach/irqs.h @@ -164,6 +164,12 @@ #define IRQ_S3CUART_TX3 IRQ_S3C2443_TX3 #define IRQ_S3CUART_ERR3 IRQ_S3C2443_ERR3 +#ifdef CONFIG_CPU_S3C2440 +#define IRQ_S3C244x_AC97 IRQ_S3C2440_AC97 +#else +#define IRQ_S3C244x_AC97 IRQ_S3C2443_AC97 +#endif + /* Our FIQs are routable from IRQ_EINT0 to IRQ_ADCPARENT */ #define FIQ_START IRQ_EINT0 diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h index e99b212cb1ca..b049e61460b6 100644 --- a/arch/arm/mach-s3c2410/include/mach/map.h +++ b/arch/arm/mach-s3c2410/include/mach/map.h @@ -67,6 +67,13 @@ #define S3C2443_PA_HSMMC (0x4A800000) #define S3C2443_SZ_HSMMC (256) +/* S3C2412 memory and IO controls */ +#define S3C2412_PA_SSMC (0x4F000000) +#define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000) + +#define S3C2412_PA_EBI (0x48800000) +#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00010000) + /* physical addresses of all the chip-select areas */ #define S3C2410_CS0 (0x00000000) @@ -103,5 +110,6 @@ #define S3C_PA_UART S3C24XX_PA_UART #define S3C_PA_USBHOST S3C2410_PA_USBHOST #define S3C_PA_HSMMC0 S3C2443_PA_HSMMC +#define S3C_PA_NAND S3C24XX_PA_NAND #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h index b278d0c45ccf..f6e8eec879c8 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h @@ -328,13 +328,15 @@ #define S3C2410_GPD8_VD16 (0x02 << 16) #define S3C2400_GPD8_TOUT3 (0x02 << 16) +#define S3C2440_GPD8_SPIMISO1 (0x03 << 16) #define S3C2410_GPD9_VD17 (0x02 << 18) #define S3C2400_GPD9_TCLK0 (0x02 << 18) -#define S3C2410_GPD9_MASK (0x03 << 18) +#define S3C2440_GPD9_SPIMOSI1 (0x03 << 18) #define S3C2410_GPD10_VD18 (0x02 << 20) #define S3C2400_GPD10_nWAIT (0x02 << 20) +#define S3C2440_GPD10_SPICLK1 (0x03 << 20) #define S3C2410_GPD11_VD19 (0x02 << 22) diff --git a/arch/arm/mach-s3c2410/include/mach/regs-mem.h b/arch/arm/mach-s3c2410/include/mach/regs-mem.h index 57759804e2fa..7f7c52947963 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-mem.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-mem.h @@ -73,6 +73,16 @@ #define S3C2410_BWSCON_WS7 (1<<30) #define S3C2410_BWSCON_ST7 (1<<31) +/* accesor functions for getting BANK(n) configuration. (n != 0) */ + +#define S3C2410_BWSCON_GET(_bwscon, _bank) (((_bwscon) >> ((_bank) * 4)) & 0xf) + +#define S3C2410_BWSCON_DW8 (0) +#define S3C2410_BWSCON_DW16 (1) +#define S3C2410_BWSCON_DW32 (2) +#define S3C2410_BWSCON_WS (1 << 2) +#define S3C2410_BWSCON_ST (1 << 3) + /* memory set (rom, ram) */ #define S3C2410_BANKCON0 S3C2410_MEMREG(0x0004) #define S3C2410_BANKCON1 S3C2410_MEMREG(0x0008) diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2412-mem.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2412-mem.h index a4bf27123170..fb6352515090 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2412-mem.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2412-mem.h @@ -14,9 +14,11 @@ #ifndef __ASM_ARM_REGS_S3C2412_MEM #define __ASM_ARM_REGS_S3C2412_MEM -#ifndef S3C2412_MEMREG #define S3C2412_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x)) -#endif +#define S3C2412_EBIREG(x) (S3C2412_VA_EBI + (x)) + +#define S3C2412_SSMCREG(x) (S3C2412_VA_SSMC + (x)) +#define S3C2412_SSMC(x, o) (S3C2412_SSMCREG((x * 0x20) + (o))) #define S3C2412_BANKCFG S3C2412_MEMREG(0x00) #define S3C2412_BANKCON1 S3C2412_MEMREG(0x04) @@ -26,4 +28,21 @@ #define S3C2412_REFRESH S3C2412_MEMREG(0x10) #define S3C2412_TIMEOUT S3C2412_MEMREG(0x14) +/* EBI control registers */ + +#define S3C2412_EBI_PR S3C2412_EBIREG(0x00) +#define S3C2412_EBI_BANKCFG S3C2412_EBIREG(0x04) + +/* SSMC control registers */ + +#define S3C2412_SSMC_BANK(x) S3C2412_SSMC(x, 0x00) +#define S3C2412_SMIDCYR(x) S3C2412_SSMC(x, 0x00) +#define S3C2412_SMBWSTRD(x) S3C2412_SSMC(x, 0x04) +#define S3C2412_SMBWSTWRR(x) S3C2412_SSMC(x, 0x08) +#define S3C2412_SMBWSTOENR(x) S3C2412_SSMC(x, 0x0C) +#define S3C2412_SMBWSTWENR(x) S3C2412_SSMC(x, 0x10) +#define S3C2412_SMBCR(x) S3C2412_SSMC(x, 0x14) +#define S3C2412_SMBSR(x) S3C2412_SSMC(x, 0x18) +#define S3C2412_SMBWSTBRDR(x) S3C2412_SSMC(x, 0x1C) + #endif /* __ASM_ARM_REGS_S3C2412_MEM */ diff --git a/arch/arm/mach-s3c2410/include/mach/spi.h b/arch/arm/mach-s3c2410/include/mach/spi.h index 1d300fb112b1..193b39d654ed 100644 --- a/arch/arm/mach-s3c2410/include/mach/spi.h +++ b/arch/arm/mach-s3c2410/include/mach/spi.h @@ -30,4 +30,7 @@ extern void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi, extern void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi, int enable); +extern void s3c24xx_spi_gpiocfg_bus1_gpd8_9_10(struct s3c2410_spi_info *spi, + int enable); + #endif /* __ASM_ARCH_SPI_H */ diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index 92150399563b..5e2f35332056 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c @@ -39,9 +39,22 @@ static struct sysdev_driver s3c2410_irq_driver = { .resume = s3c24xx_irq_resume, }; -static int s3c2410_irq_init(void) +static int __init s3c2410_irq_init(void) { return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_irq_driver); } arch_initcall(s3c2410_irq_init); + +static struct sysdev_driver s3c2410a_irq_driver = { + .add = s3c2410_irq_add, + .suspend = s3c24xx_irq_suspend, + .resume = s3c24xx_irq_resume, +}; + +static int __init s3c2410a_irq_init(void) +{ + return sysdev_driver_register(&s3c2410a_sysclass, &s3c2410a_irq_driver); +} + +arch_initcall(s3c2410a_irq_init); diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index ce3baba2cd7f..647c9adb018f 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -45,6 +45,7 @@ #include <mach/regs-mem.h> #include <mach/regs-lcd.h> +#include <plat/hwmon.h> #include <plat/nand.h> #include <plat/iic.h> #include <mach/fb.h> @@ -59,6 +60,7 @@ #include <plat/clock.h> #include <plat/devs.h> #include <plat/cpu.h> +#include <plat/cpu-freq.h> #include "usb-simtec.h" #include "nor-simtec.h" @@ -547,7 +549,35 @@ static struct i2c_board_info bast_i2c_devs[] __initdata = { }, }; +static struct s3c_hwmon_pdata bast_hwmon_info = { + /* LCD contrast (0-6.6V) */ + .in[0] = &(struct s3c_hwmon_chcfg) { + .name = "lcd-contrast", + .mult = 3300, + .div = 512, + }, + /* LED current feedback */ + .in[1] = &(struct s3c_hwmon_chcfg) { + .name = "led-feedback", + .mult = 3300, + .div = 1024, + }, + /* LCD feedback (0-6.6V) */ + .in[2] = &(struct s3c_hwmon_chcfg) { + .name = "lcd-feedback", + .mult = 3300, + .div = 512, + }, + /* Vcore (1.8-2.0V), Vref 3.3V */ + .in[3] = &(struct s3c_hwmon_chcfg) { + .name = "vcore", + .mult = 3300, + .div = 1024, + }, +}; + /* Standard BAST devices */ +// cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0 static struct platform_device *bast_devices[] __initdata = { &s3c_device_usb, @@ -556,6 +586,8 @@ static struct platform_device *bast_devices[] __initdata = { &s3c_device_i2c0, &s3c_device_rtc, &s3c_device_nand, + &s3c_device_adc, + &s3c_device_hwmon, &bast_device_dm9k, &bast_device_asix, &bast_device_axpp, @@ -570,6 +602,12 @@ static struct clk *bast_clocks[] __initdata = { &s3c24xx_uclk, }; +static struct s3c_cpufreq_board __initdata bast_cpufreq = { + .refresh = 7800, /* 7.8usec */ + .auto_io = 1, + .need_io = 1, +}; + static void __init bast_map_io(void) { /* initialise the clocks */ @@ -588,6 +626,7 @@ static void __init bast_map_io(void) s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); s3c_device_nand.dev.platform_data = &bast_nand_info; + s3c_device_hwmon.dev.platform_data = &bast_hwmon_info; s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); s3c24xx_init_clocks(0); @@ -608,6 +647,8 @@ static void __init bast_init(void) usb_simtec_init(); nor_simtec_init(); + + s3c_cpufreq_setboard(&bast_cpufreq); } MACHINE_START(BAST, "Simtec-BAST") diff --git a/arch/arm/mach-s3c2410/pll.c b/arch/arm/mach-s3c2410/pll.c new file mode 100644 index 000000000000..f178c2fd9d85 --- /dev/null +++ b/arch/arm/mach-s3c2410/pll.c @@ -0,0 +1,95 @@ +/* arch/arm/mach-s3c2410/pll.c + * + * Copyright (c) 2006,2007 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * Vincent Sanders <vince@arm.linux.org.uk> + * + * S3C2410 CPU PLL tables + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sysdev.h> +#include <linux/list.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <plat/cpu.h> +#include <plat/cpu-freq-core.h> + +static struct cpufreq_frequency_table pll_vals_12MHz[] = { + { .frequency = 34000000, .index = PLLVAL(82, 2, 3), }, + { .frequency = 45000000, .index = PLLVAL(82, 1, 3), }, + { .frequency = 51000000, .index = PLLVAL(161, 3, 3), }, + { .frequency = 48000000, .index = PLLVAL(120, 2, 3), }, + { .frequency = 56000000, .index = PLLVAL(142, 2, 3), }, + { .frequency = 68000000, .index = PLLVAL(82, 2, 2), }, + { .frequency = 79000000, .index = PLLVAL(71, 1, 2), }, + { .frequency = 85000000, .index = PLLVAL(105, 2, 2), }, + { .frequency = 90000000, .index = PLLVAL(112, 2, 2), }, + { .frequency = 101000000, .index = PLLVAL(127, 2, 2), }, + { .frequency = 113000000, .index = PLLVAL(105, 1, 2), }, + { .frequency = 118000000, .index = PLLVAL(150, 2, 2), }, + { .frequency = 124000000, .index = PLLVAL(116, 1, 2), }, + { .frequency = 135000000, .index = PLLVAL(82, 2, 1), }, + { .frequency = 147000000, .index = PLLVAL(90, 2, 1), }, + { .frequency = 152000000, .index = PLLVAL(68, 1, 1), }, + { .frequency = 158000000, .index = PLLVAL(71, 1, 1), }, + { .frequency = 170000000, .index = PLLVAL(77, 1, 1), }, + { .frequency = 180000000, .index = PLLVAL(82, 1, 1), }, + { .frequency = 186000000, .index = PLLVAL(85, 1, 1), }, + { .frequency = 192000000, .index = PLLVAL(88, 1, 1), }, + { .frequency = 203000000, .index = PLLVAL(161, 3, 1), }, + + /* 2410A extras */ + + { .frequency = 210000000, .index = PLLVAL(132, 2, 1), }, + { .frequency = 226000000, .index = PLLVAL(105, 1, 1), }, + { .frequency = 266000000, .index = PLLVAL(125, 1, 1), }, + { .frequency = 268000000, .index = PLLVAL(126, 1, 1), }, + { .frequency = 270000000, .index = PLLVAL(127, 1, 1), }, +}; + +static int s3c2410_plls_add(struct sys_device *dev) +{ + return s3c_plltab_register(pll_vals_12MHz, ARRAY_SIZE(pll_vals_12MHz)); +} + +static struct sysdev_driver s3c2410_plls_drv = { + .add = s3c2410_plls_add, +}; + +static int __init s3c2410_pll_init(void) +{ + return sysdev_driver_register(&s3c2410_sysclass, &s3c2410_plls_drv); + +} + +arch_initcall(s3c2410_pll_init); + +static struct sysdev_driver s3c2410a_plls_drv = { + .add = s3c2410_plls_add, +}; + +static int __init s3c2410a_pll_init(void) +{ + return sysdev_driver_register(&s3c2410a_sysclass, &s3c2410a_plls_drv); +} + +arch_initcall(s3c2410a_pll_init); diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index 143e08a599d4..966119c8efee 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c @@ -119,6 +119,18 @@ static int __init s3c2410_pm_drvinit(void) } arch_initcall(s3c2410_pm_drvinit); + +static struct sysdev_driver s3c2410a_pm_driver = { + .add = s3c2410_pm_add, + .resume = s3c2410_pm_resume, +}; + +static int __init s3c2410a_pm_drvinit(void) +{ + return sysdev_driver_register(&s3c2410a_sysclass, &s3c2410a_pm_driver); +} + +arch_initcall(s3c2410a_pm_drvinit); #endif #if defined(CONFIG_CPU_S3C2440) diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index feb141b1f915..91ba42f688ac 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -105,17 +105,33 @@ void __init_or_cpufreq s3c2410_setup_clocks(void) s3c24xx_setup_clocks(fclk, hclk, pclk); } +/* fake ARMCLK for use with cpufreq, etc. */ + +static struct clk s3c2410_armclk = { + .name = "armclk", + .parent = &clk_f, + .id = -1, +}; + void __init s3c2410_init_clocks(int xtal) { s3c24xx_register_baseclocks(xtal); s3c2410_setup_clocks(); s3c2410_baseclk_add(); + s3c24xx_register_clock(&s3c2410_armclk); } struct sysdev_class s3c2410_sysclass = { .name = "s3c2410-core", }; +/* Note, we would have liked to name this s3c2410-core, but we cannot + * register two sysdev_class with the same name. + */ +struct sysdev_class s3c2410a_sysclass = { + .name = "s3c2410a-core", +}; + static struct sys_device s3c2410_sysdev = { .cls = &s3c2410_sysclass, }; @@ -133,9 +149,22 @@ static int __init s3c2410_core_init(void) core_initcall(s3c2410_core_init); +static int __init s3c2410a_core_init(void) +{ + return sysdev_class_register(&s3c2410a_sysclass); +} + +core_initcall(s3c2410a_core_init); + int __init s3c2410_init(void) { printk("S3C2410: Initialising architecture\n"); return sysdev_register(&s3c2410_sysdev); } + +int __init s3c2410a_init(void) +{ + s3c2410_sysdev.cls = &s3c2410a_sysclass; + return s3c2410_init(); +} diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index 63586ffd0ae7..35c1bde89cf2 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig @@ -32,6 +32,15 @@ config S3C2412_PM help Internal config node to apply S3C2412 power management +# Note, the S3C2412 IOtiming support is in plat-s3c24xx + +config S3C2412_CPUFREQ + bool + depends on CPU_FREQ_S3C24XX && CPU_S3C2412 + select S3C2412_IOTIMING + default y + help + CPU Frequency scaling support for S3C2412 and S3C2413 SoC CPUs. menu "S3C2412 Machines" diff --git a/arch/arm/mach-s3c2412/Makefile b/arch/arm/mach-s3c2412/Makefile index 20918d5dc6a9..530ec46cbaea 100644 --- a/arch/arm/mach-s3c2412/Makefile +++ b/arch/arm/mach-s3c2412/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_S3C2412) += clock.o obj-$(CONFIG_CPU_S3C2412) += gpio.o obj-$(CONFIG_S3C2412_DMA) += dma.o obj-$(CONFIG_S3C2412_PM) += pm.o sleep.o +obj-$(CONFIG_S3C2412_CPUFREQ) += cpu-freq.o # Machine support diff --git a/arch/arm/mach-s3c2412/cpu-freq.c b/arch/arm/mach-s3c2412/cpu-freq.c new file mode 100644 index 000000000000..eb3ea1721335 --- /dev/null +++ b/arch/arm/mach-s3c2412/cpu-freq.c @@ -0,0 +1,257 @@ +/* linux/arch/arm/mach-s3c2412/cpu-freq.c + * + * Copyright 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2412 CPU Frequency scalling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/sysdev.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <mach/regs-clock.h> +#include <mach/regs-s3c2412-mem.h> + +#include <plat/cpu.h> +#include <plat/clock.h> +#include <plat/cpu-freq-core.h> + +/* our clock resources. */ +static struct clk *xtal; +static struct clk *fclk; +static struct clk *hclk; +static struct clk *armclk; + +/* HDIV: 1, 2, 3, 4, 6, 8 */ + +static int s3c2412_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) +{ + unsigned int hdiv, pdiv, armdiv, dvs; + unsigned long hclk, fclk, armclk, armdiv_clk; + unsigned long hclk_max; + + fclk = cfg->freq.fclk; + armclk = cfg->freq.armclk; + hclk_max = cfg->max.hclk; + + /* We can't run hclk above armclk as at the best we have to + * have armclk and hclk in dvs mode. */ + + if (hclk_max > armclk) + hclk_max = armclk; + + s3c_freq_dbg("%s: fclk=%lu, armclk=%lu, hclk_max=%lu\n", + __func__, fclk, armclk, hclk_max); + s3c_freq_dbg("%s: want f=%lu, arm=%lu, h=%lu, p=%lu\n", + __func__, cfg->freq.fclk, cfg->freq.armclk, + cfg->freq.hclk, cfg->freq.pclk); + + armdiv = fclk / armclk; + + if (armdiv < 1) + armdiv = 1; + if (armdiv > 2) + armdiv = 2; + + cfg->divs.arm_divisor = armdiv; + armdiv_clk = fclk / armdiv; + + hdiv = armdiv_clk / hclk_max; + if (hdiv < 1) + hdiv = 1; + + cfg->freq.hclk = hclk = armdiv_clk / hdiv; + + /* set dvs depending on whether we reached armclk or not. */ + cfg->divs.dvs = dvs = armclk < armdiv_clk; + + /* update the actual armclk we achieved. */ + cfg->freq.armclk = dvs ? hclk : armdiv_clk; + + s3c_freq_dbg("%s: armclk %lu, hclk %lu, armdiv %d, hdiv %d, dvs %d\n", + __func__, armclk, hclk, armdiv, hdiv, cfg->divs.dvs); + + if (hdiv > 4) + goto invalid; + + pdiv = (hclk > cfg->max.pclk) ? 2 : 1; + + if ((hclk / pdiv) > cfg->max.pclk) + pdiv++; + + cfg->freq.pclk = hclk / pdiv; + + s3c_freq_dbg("%s: pdiv %d\n", __func__, pdiv); + + if (pdiv > 2) + goto invalid; + + pdiv *= hdiv; + + /* store the result, and then return */ + + cfg->divs.h_divisor = hdiv * armdiv; + cfg->divs.p_divisor = pdiv * armdiv; + + return 0; + + invalid: + return -EINVAL; +} + +static void s3c2412_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) +{ + unsigned long clkdiv; + unsigned long olddiv; + + olddiv = clkdiv = __raw_readl(S3C2410_CLKDIVN); + + /* clear off current clock info */ + + clkdiv &= ~S3C2412_CLKDIVN_ARMDIVN; + clkdiv &= ~S3C2412_CLKDIVN_HDIVN_MASK; + clkdiv &= ~S3C2412_CLKDIVN_PDIVN; + + if (cfg->divs.arm_divisor == 2) + clkdiv |= S3C2412_CLKDIVN_ARMDIVN; + + clkdiv |= ((cfg->divs.h_divisor / cfg->divs.arm_divisor) - 1); + + if (cfg->divs.p_divisor != cfg->divs.h_divisor) + clkdiv |= S3C2412_CLKDIVN_PDIVN; + + s3c_freq_dbg("%s: div %08lx => %08lx\n", __func__, olddiv, clkdiv); + __raw_writel(clkdiv, S3C2410_CLKDIVN); + + clk_set_parent(armclk, cfg->divs.dvs ? hclk : fclk); +} + +static void s3c2412_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) +{ + struct s3c_cpufreq_board *board = cfg->board; + unsigned long refresh; + + s3c_freq_dbg("%s: refresh %u ns, hclk %lu\n", __func__, + board->refresh, cfg->freq.hclk); + + /* Reduce both the refresh time (in ns) and the frequency (in MHz) + * by 10 each to ensure that we do not overflow 32 bit numbers. This + * should work for HCLK up to 133MHz and refresh period up to 30usec. + */ + + refresh = (board->refresh / 10); + refresh *= (cfg->freq.hclk / 100); + refresh /= (1 * 1000 * 1000); /* 10^6 */ + + s3c_freq_dbg("%s: setting refresh 0x%08lx\n", __func__, refresh); + __raw_writel(refresh, S3C2412_REFRESH); +} + +/* set the default cpu frequency information, based on an 200MHz part + * as we have no other way of detecting the speed rating in software. + */ + +static struct s3c_cpufreq_info s3c2412_cpufreq_info = { + .max = { + .fclk = 200000000, + .hclk = 100000000, + .pclk = 50000000, + }, + + .latency = 5000000, /* 5ms */ + + .locktime_m = 150, + .locktime_u = 150, + .locktime_bits = 16, + + .name = "s3c2412", + .set_refresh = s3c2412_cpufreq_setrefresh, + .set_divs = s3c2412_cpufreq_setdivs, + .calc_divs = s3c2412_cpufreq_calcdivs, + + .calc_iotiming = s3c2412_iotiming_calc, + .set_iotiming = s3c2412_iotiming_set, + .get_iotiming = s3c2412_iotiming_get, + + .resume_clocks = s3c2412_setup_clocks, + + .debug_io_show = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs), +}; + +static int s3c2412_cpufreq_add(struct sys_device *sysdev) +{ + unsigned long fclk_rate; + + hclk = clk_get(NULL, "hclk"); + if (IS_ERR(hclk)) { + printk(KERN_ERR "%s: cannot find hclk clock\n", __func__); + return -ENOENT; + } + + fclk = clk_get(NULL, "fclk"); + if (IS_ERR(fclk)) { + printk(KERN_ERR "%s: cannot find fclk clock\n", __func__); + goto err_fclk; + } + + fclk_rate = clk_get_rate(fclk); + if (fclk_rate > 200000000) { + printk(KERN_INFO + "%s: fclk %ld MHz, assuming 266MHz capable part\n", + __func__, fclk_rate / 1000000); + s3c2412_cpufreq_info.max.fclk = 266000000; + s3c2412_cpufreq_info.max.hclk = 133000000; + s3c2412_cpufreq_info.max.pclk = 66000000; + } + + armclk = clk_get(NULL, "armclk"); + if (IS_ERR(armclk)) { + printk(KERN_ERR "%s: cannot find arm clock\n", __func__); + goto err_armclk; + } + + xtal = clk_get(NULL, "xtal"); + if (IS_ERR(xtal)) { + printk(KERN_ERR "%s: cannot find xtal clock\n", __func__); + goto err_xtal; + } + + return s3c_cpufreq_register(&s3c2412_cpufreq_info); + +err_xtal: + clk_put(armclk); +err_armclk: + clk_put(fclk); +err_fclk: + clk_put(hclk); + + return -ENOENT; +} + +static struct sysdev_driver s3c2412_cpufreq_driver = { + .add = s3c2412_cpufreq_add, +}; + +static int s3c2412_cpufreq_init(void) +{ + return sysdev_driver_register(&s3c2412_sysclass, + &s3c2412_cpufreq_driver); +} + +arch_initcall(s3c2412_cpufreq_init); diff --git a/arch/arm/mach-s3c2412/s3c2412.c b/arch/arm/mach-s3c2412/s3c2412.c index 5b5aba69ec3f..bef39f77729d 100644 --- a/arch/arm/mach-s3c2412/s3c2412.c +++ b/arch/arm/mach-s3c2412/s3c2412.c @@ -69,6 +69,18 @@ static struct map_desc s3c2412_iodesc[] __initdata = { IODESC_ENT(CLKPWR), IODESC_ENT(TIMER), IODESC_ENT(WATCHDOG), + { + .virtual = (unsigned long)S3C2412_VA_SSMC, + .pfn = __phys_to_pfn(S3C2412_PA_SSMC), + .length = SZ_1M, + .type = MT_DEVICE, + }, + { + .virtual = (unsigned long)S3C2412_VA_EBI, + .pfn = __phys_to_pfn(S3C2412_PA_EBI), + .length = SZ_1M, + .type = MT_DEVICE, + }, }; /* uart registration process */ diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index 8cfeaec37306..8ae1b288f7fa 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig @@ -33,6 +33,7 @@ config MACH_ANUBIS select PM_SIMTEC if PM select HAVE_PATA_PLATFORM select S3C24XX_GPIO_EXTRA64 + select S3C2440_XTAL_12000000 select S3C_DEV_USB_HOST help Say Y here if you are using the Simtec Electronics ANUBIS @@ -44,6 +45,8 @@ config MACH_OSIRIS select S3C24XX_DCLK select PM_SIMTEC if PM select S3C24XX_GPIO_EXTRA128 + select S3C2440_XTAL_12000000 + select S3C2410_IOTIMING if S3C2440_CPUFREQ select S3C_DEV_USB_HOST help Say Y here if you are using the Simtec IM2440D20 module, also @@ -52,6 +55,7 @@ config MACH_OSIRIS config MACH_RX3715 bool "HP iPAQ rx3715" select CPU_S3C2440 + select S3C2440_XTAL_16934400 select PM_H1940 if PM help Say Y here if you are using the HP iPAQ rx3715. @@ -59,6 +63,7 @@ config MACH_RX3715 config ARCH_S3C2440 bool "SMDK2440" select CPU_S3C2440 + select S3C2440_XTAL_16934400 select MACH_SMDK select S3C_DEV_USB_HOST help @@ -67,6 +72,7 @@ config ARCH_S3C2440 config MACH_NEXCODER_2440 bool "NexVision NEXCODER 2440 Light Board" select CPU_S3C2440 + select S3C2440_XTAL_12000000 select S3C_DEV_USB_HOST help Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board @@ -75,6 +81,7 @@ config SMDK2440_CPU2440 bool "SMDK2440 with S3C2440 CPU module" depends on ARCH_S3C2440 default y if ARCH_S3C2440 + select S3C2440_XTAL_16934400 select CPU_S3C2440 config MACH_AT2440EVB diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index cba064b49a64..2105a41281a4 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -34,6 +34,7 @@ #include <asm/irq.h> #include <asm/mach-types.h> +#include <plat/cpu-freq.h> #include <plat/regs-serial.h> #include <mach/regs-gpio.h> #include <mach/regs-mem.h> @@ -351,6 +352,12 @@ static struct clk *osiris_clocks[] __initdata = { &s3c24xx_uclk, }; +static struct s3c_cpufreq_board __initdata osiris_cpufreq = { + .refresh = 7800, /* refresh period is 7.8usec */ + .auto_io = 1, + .need_io = 1, +}; + static void __init osiris_map_io(void) { unsigned long flags; @@ -402,6 +409,8 @@ static void __init osiris_init(void) s3c_i2c0_set_platdata(NULL); + s3c_cpufreq_setboard(&osiris_cpufreq); + i2c_register_board_info(0, osiris_i2c_devs, ARRAY_SIZE(osiris_i2c_devs)); diff --git a/arch/arm/mach-s3c24a0/include/mach/map.h b/arch/arm/mach-s3c24a0/include/mach/map.h index a01132717e34..79e4d93ea2b6 100644 --- a/arch/arm/mach-s3c24a0/include/mach/map.h +++ b/arch/arm/mach-s3c24a0/include/mach/map.h @@ -81,5 +81,6 @@ #define S3C_PA_UART S3C24A0_PA_UART #define S3C_PA_IIC S3C24A0_PA_IIC +#define S3C_PA_NAND S3C24XX_PA_NAND #endif /* __ASM_ARCH_24A0_MAP_H */ diff --git a/arch/arm/mach-s3c6400/include/mach/map.h b/arch/arm/mach-s3c6400/include/mach/map.h index 5057d9948d35..fc8b223bad4f 100644 --- a/arch/arm/mach-s3c6400/include/mach/map.h +++ b/arch/arm/mach-s3c6400/include/mach/map.h @@ -38,18 +38,21 @@ #define S3C_VA_UART2 S3C_VA_UARTx(2) #define S3C_VA_UART3 S3C_VA_UARTx(3) +#define S3C64XX_PA_NAND (0x70200000) #define S3C64XX_PA_FB (0x77100000) #define S3C64XX_PA_USB_HSOTG (0x7C000000) #define S3C64XX_PA_WATCHDOG (0x7E004000) #define S3C64XX_PA_SYSCON (0x7E00F000) +#define S3C64XX_PA_AC97 (0x7F001000) #define S3C64XX_PA_IIS0 (0x7F002000) #define S3C64XX_PA_IIS1 (0x7F003000) #define S3C64XX_PA_TIMER (0x7F006000) #define S3C64XX_PA_IIC0 (0x7F004000) +#define S3C64XX_PA_IISV4 (0x7F00D000) #define S3C64XX_PA_IIC1 (0x7F00F000) #define S3C64XX_PA_GPIO (0x7F008000) -#define S3C64XX_VA_GPIO S3C_ADDR(0x00500000) +#define S3C64XX_VA_GPIO S3C_ADDR_CPU(0x00000000) #define S3C64XX_SZ_GPIO SZ_4K #define S3C64XX_PA_SDRAM (0x50000000) @@ -57,7 +60,7 @@ #define S3C64XX_PA_VIC1 (0x71300000) #define S3C64XX_PA_MODEM (0x74108000) -#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000) +#define S3C64XX_VA_MODEM S3C_ADDR_CPU(0x00100000) #define S3C64XX_PA_USBHOST (0x74300000) @@ -72,6 +75,7 @@ #define S3C_PA_HSMMC2 S3C64XX_PA_HSMMC2 #define S3C_PA_IIC S3C64XX_PA_IIC0 #define S3C_PA_IIC1 S3C64XX_PA_IIC1 +#define S3C_PA_NAND S3C64XX_PA_NAND #define S3C_PA_FB S3C64XX_PA_FB #define S3C_PA_USBHOST S3C64XX_PA_USBHOST #define S3C_PA_USB_HSOTG S3C64XX_PA_USB_HSOTG diff --git a/arch/arm/mach-s3c6400/s3c6400.c b/arch/arm/mach-s3c6400/s3c6400.c index 1ece887d90bb..b42bdd0f2138 100644 --- a/arch/arm/mach-s3c6400/s3c6400.c +++ b/arch/arm/mach-s3c6400/s3c6400.c @@ -48,6 +48,8 @@ void __init s3c6400_map_io(void) /* the i2c devices are directly compatible with s3c2440 */ s3c_i2c0_setname("s3c2440-i2c"); + + s3c_device_nand.name = "s3c6400-nand"; } void __init s3c6400_init_clocks(int xtal) diff --git a/arch/arm/mach-s3c6410/Kconfig b/arch/arm/mach-s3c6410/Kconfig index e63aac7f4e5a..f9d0f09f9761 100644 --- a/arch/arm/mach-s3c6410/Kconfig +++ b/arch/arm/mach-s3c6410/Kconfig @@ -97,3 +97,13 @@ config MACH_NCP select S3C64XX_SETUP_I2C1 help Machine support for the Samsung NCP + +config MACH_HMT + bool "Airgoo HMT" + select CPU_S3C6410 + select S3C_DEV_FB + select S3C_DEV_USB_HOST + select S3C64XX_SETUP_FB_24BPP + select HAVE_PWM + help + Machine support for the Airgoo HMT diff --git a/arch/arm/mach-s3c6410/Makefile b/arch/arm/mach-s3c6410/Makefile index 6f9deac88612..3e48c3dbf973 100644 --- a/arch/arm/mach-s3c6410/Makefile +++ b/arch/arm/mach-s3c6410/Makefile @@ -23,5 +23,4 @@ obj-$(CONFIG_S3C6410_SETUP_SDHCI) += setup-sdhci.o obj-$(CONFIG_MACH_ANW6410) += mach-anw6410.o obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o obj-$(CONFIG_MACH_NCP) += mach-ncp.o - - +obj-$(CONFIG_MACH_HMT) += mach-hmt.o diff --git a/arch/arm/mach-s3c6410/cpu.c b/arch/arm/mach-s3c6410/cpu.c index ade904de8895..9b67c663d9d8 100644 --- a/arch/arm/mach-s3c6410/cpu.c +++ b/arch/arm/mach-s3c6410/cpu.c @@ -62,6 +62,8 @@ void __init s3c6410_map_io(void) /* the i2c devices are directly compatible with s3c2440 */ s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); + + s3c_device_nand.name = "s3c6400-nand"; } void __init s3c6410_init_clocks(int xtal) diff --git a/arch/arm/mach-s3c6410/mach-hmt.c b/arch/arm/mach-s3c6410/mach-hmt.c new file mode 100644 index 000000000000..c5741056193f --- /dev/null +++ b/arch/arm/mach-s3c6410/mach-hmt.c @@ -0,0 +1,276 @@ +/* mach-hmt.c - Platform code for Airgoo HMT + * + * Copyright 2009 Peter Korsgaard <jacmet@sunsite.dk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/i2c.h> +#include <linux/fb.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <linux/leds.h> +#include <linux/pwm_backlight.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/regs-fb.h> +#include <mach/map.h> + +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include <plat/regs-serial.h> +#include <plat/iic.h> +#include <plat/fb.h> +#include <plat/nand.h> + +#include <plat/s3c6410.h> +#include <plat/clock.h> +#include <plat/devs.h> +#include <plat/cpu.h> + +#define UCON S3C2410_UCON_DEFAULT +#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE) +#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) + +static struct s3c2410_uartcfg hmt_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, +}; + +static int hmt_bl_init(struct device *dev) +{ + int ret; + + ret = gpio_request(S3C64XX_GPB(4), "lcd backlight enable"); + if (!ret) + ret = gpio_direction_output(S3C64XX_GPB(4), 0); + + return ret; +} + +static int hmt_bl_notify(int brightness) +{ + /* + * translate from CIELUV/CIELAB L*->brightness, E.G. from + * perceived luminance to light output. Assumes range 0..25600 + */ + if (brightness < 0x800) { + /* Y = Yn * L / 903.3 */ + brightness = (100*256 * brightness + 231245/2) / 231245; + } else { + /* Y = Yn * ((L + 16) / 116 )^3 */ + int t = (brightness*4 + 16*1024 + 58)/116; + brightness = 25 * ((t * t * t + 0x100000/2) / 0x100000); + } + + gpio_set_value(S3C64XX_GPB(4), brightness); + + return brightness; +} + +static void hmt_bl_exit(struct device *dev) +{ + gpio_free(S3C64XX_GPB(4)); +} + +static struct platform_pwm_backlight_data hmt_backlight_data = { + .pwm_id = 1, + .max_brightness = 100 * 256, + .dft_brightness = 40 * 256, + .pwm_period_ns = 1000000000 / (100 * 256 * 20), + .init = hmt_bl_init, + .notify = hmt_bl_notify, + .exit = hmt_bl_exit, + +}; + +static struct platform_device hmt_backlight_device = { + .name = "pwm-backlight", + .dev = { + .parent = &s3c_device_timer[1].dev, + .platform_data = &hmt_backlight_data, + }, +}; + +static struct s3c_fb_pd_win hmt_fb_win0 = { + .win_mode = { + .pixclock = 41094, + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .max_bpp = 32, + .default_bpp = 16, +}; + +/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */ +static struct s3c_fb_platdata hmt_lcd_pdata __initdata = { + .setup_gpio = s3c64xx_fb_gpio_setup_24bpp, + .win[0] = &hmt_fb_win0, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, +}; + +static struct mtd_partition hmt_nand_part[] = { + [0] = { + .name = "uboot", + .size = SZ_512K, + .offset = 0, + }, + [1] = { + .name = "uboot-env1", + .size = SZ_256K, + .offset = SZ_512K, + }, + [2] = { + .name = "uboot-env2", + .size = SZ_256K, + .offset = SZ_512K + SZ_256K, + }, + [3] = { + .name = "kernel", + .size = SZ_2M, + .offset = SZ_1M, + }, + [4] = { + .name = "rootfs", + .size = MTDPART_SIZ_FULL, + .offset = SZ_1M + SZ_2M, + }, +}; + +static struct s3c2410_nand_set hmt_nand_sets[] = { + [0] = { + .name = "nand", + .nr_chips = 1, + .nr_partitions = ARRAY_SIZE(hmt_nand_part), + .partitions = hmt_nand_part, + }, +}; + +static struct s3c2410_platform_nand hmt_nand_info = { + .tacls = 25, + .twrph0 = 55, + .twrph1 = 40, + .nr_sets = ARRAY_SIZE(hmt_nand_sets), + .sets = hmt_nand_sets, +}; + +static struct gpio_led hmt_leds[] = { + { /* left function keys */ + .name = "left:blue", + .gpio = S3C64XX_GPO(12), + .default_trigger = "default-on", + }, + { /* right function keys - red */ + .name = "right:red", + .gpio = S3C64XX_GPO(13), + }, + { /* right function keys - green */ + .name = "right:green", + .gpio = S3C64XX_GPO(14), + }, + { /* right function keys - blue */ + .name = "right:blue", + .gpio = S3C64XX_GPO(15), + .default_trigger = "default-on", + }, +}; + +static struct gpio_led_platform_data hmt_led_data = { + .num_leds = ARRAY_SIZE(hmt_leds), + .leds = hmt_leds, +}; + +static struct platform_device hmt_leds_device = { + .name = "leds-gpio", + .id = -1, + .dev.platform_data = &hmt_led_data, +}; + +static struct map_desc hmt_iodesc[] = {}; + +static struct platform_device *hmt_devices[] __initdata = { + &s3c_device_i2c0, + &s3c_device_nand, + &s3c_device_fb, + &s3c_device_usb, + &s3c_device_timer[1], + &hmt_backlight_device, + &hmt_leds_device, +}; + +static void __init hmt_map_io(void) +{ + s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs)); +} + +static void __init hmt_machine_init(void) +{ + s3c_i2c0_set_platdata(NULL); + s3c_fb_set_platdata(&hmt_lcd_pdata); + s3c_device_nand.dev.platform_data = &hmt_nand_info; + + gpio_request(S3C64XX_GPC(7), "usb power"); + gpio_direction_output(S3C64XX_GPC(7), 0); + gpio_request(S3C64XX_GPM(0), "usb power"); + gpio_direction_output(S3C64XX_GPM(0), 1); + gpio_request(S3C64XX_GPK(7), "usb power"); + gpio_direction_output(S3C64XX_GPK(7), 1); + gpio_request(S3C64XX_GPF(13), "usb power"); + gpio_direction_output(S3C64XX_GPF(13), 1); + + platform_add_devices(hmt_devices, ARRAY_SIZE(hmt_devices)); +} + +MACHINE_START(HMT, "Airgoo-HMT") + /* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */ + .phys_io = S3C_PA_UART & 0xfff00000, + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C64XX_PA_SDRAM + 0x100, + .init_irq = s3c6410_init_irq, + .map_io = hmt_map_io, + .init_machine = hmt_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-s3c6410/mach-ncp.c b/arch/arm/mach-s3c6410/mach-ncp.c index 6030636f8548..55e9bbfaf68b 100644 --- a/arch/arm/mach-s3c6410/mach-ncp.c +++ b/arch/arm/mach-s3c6410/mach-ncp.c @@ -79,7 +79,7 @@ static struct platform_device *ncp_devices[] __initdata = { &s3c_device_i2c0, }; -struct map_desc ncp_iodesc[] = {}; +static struct map_desc ncp_iodesc[] __initdata = {}; static void __init ncp_map_io(void) { diff --git a/arch/arm/mach-s3c6410/mach-smdk6410.c b/arch/arm/mach-s3c6410/mach-smdk6410.c index bc9a7dea567f..ea51dbe76e3e 100644 --- a/arch/arm/mach-s3c6410/mach-smdk6410.c +++ b/arch/arm/mach-s3c6410/mach-smdk6410.c @@ -65,16 +65,30 @@ static struct s3c2410_uartcfg smdk6410_uartcfgs[] __initdata = { [0] = { .hwport = 0, .flags = 0, - .ucon = 0x3c5, - .ulcon = 0x03, - .ufcon = 0x51, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, [1] = { .hwport = 1, .flags = 0, - .ucon = 0x3c5, - .ulcon = 0x03, - .ufcon = 0x51, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, }, }; diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig new file mode 100644 index 000000000000..b1a4ba504416 --- /dev/null +++ b/arch/arm/mach-s5pc100/Kconfig @@ -0,0 +1,22 @@ +# arch/arm/mach-s5pc100/Kconfig +# +# Copyright 2009 Samsung Electronics Co. +# Byungho Min <bhmin@samsung.com> +# +# Licensed under GPLv2 + +# Configuration options for the S5PC100 CPU + +config CPU_S5PC100 + bool + select CPU_S5PC100_INIT + select CPU_S5PC100_CLOCK + help + Enable S5PC100 CPU support + +config MACH_SMDKC100 + bool "SMDKC100" + select CPU_S5PC100 + select S5PC1XX_SETUP_I2C1 + help + Machine support for the Samsung SMDKC100 diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile new file mode 100644 index 000000000000..afc89b381d7a --- /dev/null +++ b/arch/arm/mach-s5pc100/Makefile @@ -0,0 +1,17 @@ +# arch/arm/mach-s5pc100/Makefile +# +# Copyright 2009 Samsung Electronics Co. +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +# Core support for S5PC100 system + +obj-$(CONFIG_CPU_S5PC100) += cpu.o + +# machine support +obj-$(CONFIG_MACH_SMDKC100) += mach-smdkc100.o diff --git a/arch/arm/mach-s5pc100/Makefile.boot b/arch/arm/mach-s5pc100/Makefile.boot new file mode 100644 index 000000000000..ff90aa13bd67 --- /dev/null +++ b/arch/arm/mach-s5pc100/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x20008000 +params_phys-y := 0x20000100 diff --git a/arch/arm/mach-s5pc100/cpu.c b/arch/arm/mach-s5pc100/cpu.c new file mode 100644 index 000000000000..0e718890da32 --- /dev/null +++ b/arch/arm/mach-s5pc100/cpu.c @@ -0,0 +1,97 @@ +/* linux/arch/arm/mach-s5pc100/cpu.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Based on mach-s3c6410/cpu.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/sysdev.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <mach/hardware.h> +#include <mach/map.h> +#include <asm/irq.h> + +#include <plat/cpu-freq.h> +#include <plat/regs-serial.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> +#include <plat/sdhci.h> +#include <plat/iic-core.h> +#include <plat/s5pc100.h> + +/* Initial IO mappings */ + +static struct map_desc s5pc100_iodesc[] __initdata = { +}; + +/* s5pc100_map_io + * + * register the standard cpu IO areas +*/ + +void __init s5pc100_map_io(void) +{ + iotable_init(s5pc100_iodesc, ARRAY_SIZE(s5pc100_iodesc)); + + /* initialise device information early */ +} + +void __init s5pc100_init_clocks(int xtal) +{ + printk(KERN_DEBUG "%s: initialising clocks\n", __func__); + s3c24xx_register_baseclocks(xtal); + s5pc1xx_register_clocks(); + s5pc100_register_clocks(); + s5pc100_setup_clocks(); +} + +void __init s5pc100_init_irq(void) +{ + u32 vic_valid[] = {~0, ~0, ~0}; + + /* VIC0, VIC1, and VIC2 are fully populated. */ + s5pc1xx_init_irq(vic_valid, ARRAY_SIZE(vic_valid)); +} + +struct sysdev_class s5pc100_sysclass = { + .name = "s5pc100-core", +}; + +static struct sys_device s5pc100_sysdev = { + .cls = &s5pc100_sysclass, +}; + +static int __init s5pc100_core_init(void) +{ + return sysdev_class_register(&s5pc100_sysclass); +} + +core_initcall(s5pc100_core_init); + +int __init s5pc100_init(void) +{ + printk(KERN_DEBUG "S5PC100: Initialising architecture\n"); + + return sysdev_register(&s5pc100_sysdev); +} diff --git a/arch/arm/mach-s5pc100/include/mach/debug-macro.S b/arch/arm/mach-s5pc100/include/mach/debug-macro.S new file mode 100644 index 000000000000..9d142ccf654b --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/debug-macro.S @@ -0,0 +1,38 @@ +/* arch/arm/mach-s5pc100/include/mach/debug-macro.S + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * + * Based on mach-s3c6400/include/mach/debug-macro.S + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* pull in the relevant register and map files. */ + +#include <mach/map.h> +#include <plat/regs-serial.h> + + /* note, for the boot process to work we have to keep the UART + * virtual address aligned to an 1MiB boundary for the L1 + * mapping the head code makes. We keep the UART virtual address + * aligned and add in the offset when we load the value here. + */ + + .macro addruart, rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 + ldreq \rx, = S3C_PA_UART + ldrne \rx, = (S3C_VA_UART + S3C_PA_UART & 0xfffff) + add \rx, \rx, #(0x400 * CONFIG_DEBUG_S3C_UART) + .endm + +/* include the reset of the code which will do the work, we're only + * compiling for a single cpu processor type so the default of s3c2440 + * will be fine with us. + */ + +#include <plat/debug-macro.S> diff --git a/arch/arm/mach-s5pc100/include/mach/entry-macro.S b/arch/arm/mach-s5pc100/include/mach/entry-macro.S new file mode 100644 index 000000000000..67131939e626 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/entry-macro.S @@ -0,0 +1,50 @@ +/* arch/arm/mach-s5pc100/include/mach/entry-macro.S + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Based on mach-s3c6400/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for the Samsung S5PC1XX series + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. +*/ + +#include <asm/hardware/vic.h> +#include <mach/map.h> +#include <plat/irqs.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =S3C_VA_VIC0 + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + @ check the vic0 + mov \irqnr, # S3C_IRQ_OFFSET + 31 + ldr \irqstat, [ \base, # VIC_IRQ_STATUS ] + teq \irqstat, #0 + + @ otherwise try vic1 + addeq \tmp, \base, #(S3C_VA_VIC1 - S3C_VA_VIC0) + addeq \irqnr, \irqnr, #32 + ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] + teqeq \irqstat, #0 + + @ otherwise try vic2 + addeq \tmp, \base, #(S3C_VA_VIC2 - S3C_VA_VIC0) + addeq \irqnr, \irqnr, #32 + ldreq \irqstat, [ \tmp, # VIC_IRQ_STATUS ] + teqeq \irqstat, #0 + + clzne \irqstat, \irqstat + subne \irqnr, \irqnr, \irqstat + .endm diff --git a/arch/arm/mach-s5pc100/include/mach/gpio-core.h b/arch/arm/mach-s5pc100/include/mach/gpio-core.h new file mode 100644 index 000000000000..ad28d8ec8a78 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/gpio-core.h @@ -0,0 +1,21 @@ +/* arch/arm/mach-s5pc100/include/mach/gpio-core.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 - GPIO core support + * + * Based on mach-s3c6400/include/mach/gpio-core.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_GPIO_CORE_H +#define __ASM_ARCH_GPIO_CORE_H __FILE__ + +/* currently we just include the platform support */ +#include <plat/gpio-core.h> + +#endif /* __ASM_ARCH_GPIO_CORE_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h new file mode 100644 index 000000000000..c74fc93d7d15 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/gpio.h @@ -0,0 +1,146 @@ +/* arch/arm/mach-s5pc100/include/mach/gpio.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 - GPIO lib support + * + * Base on mach-s3c6400/include/mach/gpio.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +/* GPIO bank sizes */ +#define S5PC1XX_GPIO_A0_NR (8) +#define S5PC1XX_GPIO_A1_NR (5) +#define S5PC1XX_GPIO_B_NR (8) +#define S5PC1XX_GPIO_C_NR (5) +#define S5PC1XX_GPIO_D_NR (7) +#define S5PC1XX_GPIO_E0_NR (8) +#define S5PC1XX_GPIO_E1_NR (6) +#define S5PC1XX_GPIO_F0_NR (8) +#define S5PC1XX_GPIO_F1_NR (8) +#define S5PC1XX_GPIO_F2_NR (8) +#define S5PC1XX_GPIO_F3_NR (4) +#define S5PC1XX_GPIO_G0_NR (8) +#define S5PC1XX_GPIO_G1_NR (3) +#define S5PC1XX_GPIO_G2_NR (7) +#define S5PC1XX_GPIO_G3_NR (7) +#define S5PC1XX_GPIO_H0_NR (8) +#define S5PC1XX_GPIO_H1_NR (8) +#define S5PC1XX_GPIO_H2_NR (8) +#define S5PC1XX_GPIO_H3_NR (8) +#define S5PC1XX_GPIO_I_NR (8) +#define S5PC1XX_GPIO_J0_NR (8) +#define S5PC1XX_GPIO_J1_NR (5) +#define S5PC1XX_GPIO_J2_NR (8) +#define S5PC1XX_GPIO_J3_NR (8) +#define S5PC1XX_GPIO_J4_NR (4) +#define S5PC1XX_GPIO_K0_NR (8) +#define S5PC1XX_GPIO_K1_NR (6) +#define S5PC1XX_GPIO_K2_NR (8) +#define S5PC1XX_GPIO_K3_NR (8) +#define S5PC1XX_GPIO_MP00_NR (8) +#define S5PC1XX_GPIO_MP01_NR (8) +#define S5PC1XX_GPIO_MP02_NR (8) +#define S5PC1XX_GPIO_MP03_NR (8) +#define S5PC1XX_GPIO_MP04_NR (5) + +/* GPIO bank numbes */ + +/* CONFIG_S3C_GPIO_SPACE allows the user to select extra + * space for debugging purposes so that any accidental + * change from one gpio bank to another can be caught. +*/ + +#define S5PC1XX_GPIO_NEXT(__gpio) \ + ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) + +enum s3c_gpio_number { + S5PC1XX_GPIO_A0_START = 0, + S5PC1XX_GPIO_A1_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_A0), + S5PC1XX_GPIO_B_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_A1), + S5PC1XX_GPIO_C_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_B), + S5PC1XX_GPIO_D_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_C), + S5PC1XX_GPIO_E0_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_D), + S5PC1XX_GPIO_E1_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_E0), + S5PC1XX_GPIO_F0_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_E1), + S5PC1XX_GPIO_F1_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_F0), + S5PC1XX_GPIO_F2_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_F1), + S5PC1XX_GPIO_F3_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_F2), + S5PC1XX_GPIO_G0_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_F3), + S5PC1XX_GPIO_G1_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_G0), + S5PC1XX_GPIO_G2_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_G1), + S5PC1XX_GPIO_G3_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_G2), + S5PC1XX_GPIO_H0_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_G3), + S5PC1XX_GPIO_H1_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_H0), + S5PC1XX_GPIO_H2_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_H1), + S5PC1XX_GPIO_H3_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_H2), + S5PC1XX_GPIO_I_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_H3), + S5PC1XX_GPIO_J0_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_I), + S5PC1XX_GPIO_J1_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_J0), + S5PC1XX_GPIO_J2_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_J1), + S5PC1XX_GPIO_J3_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_J2), + S5PC1XX_GPIO_J4_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_J3), + S5PC1XX_GPIO_K0_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_J4), + S5PC1XX_GPIO_K1_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_K0), + S5PC1XX_GPIO_K2_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_K1), + S5PC1XX_GPIO_K3_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_K2), + S5PC1XX_GPIO_MP00_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_K3), + S5PC1XX_GPIO_MP01_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_MP00), + S5PC1XX_GPIO_MP02_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_MP01), + S5PC1XX_GPIO_MP03_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_MP02), + S5PC1XX_GPIO_MP04_START = S5PC1XX_GPIO_NEXT(S5PC1XX_GPIO_MP03), +}; + +/* S5PC1XX GPIO number definitions. */ +#define S5PC1XX_GPA0(_nr) (S5PC1XX_GPIO_A0_START + (_nr)) +#define S5PC1XX_GPA1(_nr) (S5PC1XX_GPIO_A1_START + (_nr)) +#define S5PC1XX_GPB(_nr) (S5PC1XX_GPIO_B_START + (_nr)) +#define S5PC1XX_GPC(_nr) (S5PC1XX_GPIO_C_START + (_nr)) +#define S5PC1XX_GPD(_nr) (S5PC1XX_GPIO_D_START + (_nr)) +#define S5PC1XX_GPE0(_nr) (S5PC1XX_GPIO_E0_START + (_nr)) +#define S5PC1XX_GPE1(_nr) (S5PC1XX_GPIO_E1_START + (_nr)) +#define S5PC1XX_GPF0(_nr) (S5PC1XX_GPIO_F0_START + (_nr)) +#define S5PC1XX_GPF1(_nr) (S5PC1XX_GPIO_F1_START + (_nr)) +#define S5PC1XX_GPF2(_nr) (S5PC1XX_GPIO_F2_START + (_nr)) +#define S5PC1XX_GPF3(_nr) (S5PC1XX_GPIO_F3_START + (_nr)) +#define S5PC1XX_GPG0(_nr) (S5PC1XX_GPIO_G0_START + (_nr)) +#define S5PC1XX_GPG1(_nr) (S5PC1XX_GPIO_G1_START + (_nr)) +#define S5PC1XX_GPG2(_nr) (S5PC1XX_GPIO_G2_START + (_nr)) +#define S5PC1XX_GPG3(_nr) (S5PC1XX_GPIO_G3_START + (_nr)) +#define S5PC1XX_GPH0(_nr) (S5PC1XX_GPIO_H0_START + (_nr)) +#define S5PC1XX_GPH1(_nr) (S5PC1XX_GPIO_H1_START + (_nr)) +#define S5PC1XX_GPH2(_nr) (S5PC1XX_GPIO_H2_START + (_nr)) +#define S5PC1XX_GPH3(_nr) (S5PC1XX_GPIO_H3_START + (_nr)) +#define S5PC1XX_GPI(_nr) (S5PC1XX_GPIO_I_START + (_nr)) +#define S5PC1XX_GPJ0(_nr) (S5PC1XX_GPIO_J0_START + (_nr)) +#define S5PC1XX_GPJ1(_nr) (S5PC1XX_GPIO_J1_START + (_nr)) +#define S5PC1XX_GPJ2(_nr) (S5PC1XX_GPIO_J2_START + (_nr)) +#define S5PC1XX_GPJ3(_nr) (S5PC1XX_GPIO_J3_START + (_nr)) +#define S5PC1XX_GPJ4(_nr) (S5PC1XX_GPIO_J4_START + (_nr)) +#define S5PC1XX_GPK0(_nr) (S5PC1XX_GPIO_K0_START + (_nr)) +#define S5PC1XX_GPK1(_nr) (S5PC1XX_GPIO_K1_START + (_nr)) +#define S5PC1XX_GPK2(_nr) (S5PC1XX_GPIO_K2_START + (_nr)) +#define S5PC1XX_GPK3(_nr) (S5PC1XX_GPIO_K3_START + (_nr)) +#define S5PC1XX_MP00(_nr) (S5PC1XX_GPIO_MP00_START + (_nr)) +#define S5PC1XX_MP01(_nr) (S5PC1XX_GPIO_MP01_START + (_nr)) +#define S5PC1XX_MP02(_nr) (S5PC1XX_GPIO_MP02_START + (_nr)) +#define S5PC1XX_MP03(_nr) (S5PC1XX_GPIO_MP03_START + (_nr)) +#define S5PC1XX_MP04(_nr) (S5PC1XX_GPIO_MP04_START + (_nr)) + +/* the end of the S5PC1XX specific gpios */ +#define S5PC1XX_GPIO_END (S5PC1XX_MP04(S5PC1XX_GPIO_MP04_NR) + 1) +#define S3C_GPIO_END S5PC1XX_GPIO_END + +/* define the number of gpios we need to the one after the MP04() range */ +#define ARCH_NR_GPIOS (S5PC1XX_MP04(S5PC1XX_GPIO_MP04_NR) + 1) + +#include <asm-generic/gpio.h> diff --git a/arch/arm/mach-s5pc100/include/mach/hardware.h b/arch/arm/mach-s5pc100/include/mach/hardware.h new file mode 100644 index 000000000000..6b38618c2fd9 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/hardware.h @@ -0,0 +1,14 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/hardware.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 - Hardware support + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H __FILE__ + +/* currently nothing here, placeholder */ + +#endif /* __ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h new file mode 100644 index 000000000000..622720dba289 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/irqs.h @@ -0,0 +1,14 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/irqs.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 - IRQ definitions + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H __FILE__ + +#include <plat/irqs.h> + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h new file mode 100644 index 000000000000..9e9f39130b2c --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -0,0 +1,75 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/map.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Based on mach-s3c6400/include/mach/map.h + * + * S5PC1XX - Memory map definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_MAP_H +#define __ASM_ARCH_MAP_H __FILE__ + +#include <plat/map-base.h> + + +/* Chip ID */ +#define S5PC100_PA_CHIPID (0xE0000000) +#define S5PC1XX_PA_CHIPID S5PC100_PA_CHIPID +#define S5PC1XX_VA_CHIPID S3C_VA_SYS + +/* System */ +#define S5PC100_PA_SYS (0xE0100000) +#define S5PC100_PA_CLK (S5PC100_PA_SYS + 0x0) +#define S5PC100_PA_PWR (S5PC100_PA_SYS + 0x8000) +#define S5PC1XX_PA_CLK S5PC100_PA_CLK +#define S5PC1XX_PA_PWR S5PC100_PA_PWR +#define S5PC1XX_VA_CLK (S3C_VA_SYS + 0x10000) +#define S5PC1XX_VA_PWR (S3C_VA_SYS + 0x20000) + +/* Interrupt */ +#define S5PC100_PA_VIC (0xE4000000) +#define S5PC100_VA_VIC S3C_VA_IRQ +#define S5PC100_PA_VIC_OFFSET 0x100000 +#define S5PC100_VA_VIC_OFFSET 0x10000 +#define S5PC1XX_PA_VIC(x) (S5PC100_PA_VIC + ((x) * S5PC100_PA_VIC_OFFSET)) +#define S5PC1XX_VA_VIC(x) (S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET)) + +/* Timer */ +#define S5PC100_PA_TIMER (0xEA000000) +#define S5PC1XX_PA_TIMER S5PC100_PA_TIMER +#define S5PC1XX_VA_TIMER S3C_VA_TIMER + +/* UART */ +#define S5PC100_PA_UART (0xEC000000) +#define S5PC1XX_PA_UART S5PC100_PA_UART +#define S5PC1XX_VA_UART S3C_VA_UART + +/* IIC */ +#define S5PC100_PA_IIC (0xEC100000) + +/* ETC */ +#define S5PC100_PA_SDRAM (0x20000000) + +/* compatibility defines. */ +#define S3C_PA_UART S5PC100_PA_UART +#define S3C_PA_UART0 (S5PC100_PA_UART + 0x0) +#define S3C_PA_UART1 (S5PC100_PA_UART + 0x400) +#define S3C_PA_UART2 (S5PC100_PA_UART + 0x800) +#define S3C_PA_UART3 (S5PC100_PA_UART + 0xC00) +#define S3C_VA_UART0 (S3C_VA_UART + 0x0) +#define S3C_VA_UART1 (S3C_VA_UART + 0x400) +#define S3C_VA_UART2 (S3C_VA_UART + 0x800) +#define S3C_VA_UART3 (S3C_VA_UART + 0xC00) +#define S3C_UART_OFFSET 0x400 +#define S3C_VA_VIC0 (S3C_VA_IRQ + 0x0) +#define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000) +#define S3C_VA_VIC2 (S3C_VA_IRQ + 0x20000) +#define S3C_PA_IIC S5PC100_PA_IIC + +#endif /* __ASM_ARCH_C100_MAP_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/memory.h b/arch/arm/mach-s5pc100/include/mach/memory.h new file mode 100644 index 000000000000..4b60d18179f7 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/memory.h @@ -0,0 +1,18 @@ +/* arch/arm/mach-s5pc100/include/mach/memory.h + * + * Copyright 2008 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Based on mach-s3c6400/include/mach/memory.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x20000000) + +#endif diff --git a/arch/arm/mach-s5pc100/include/mach/pwm-clock.h b/arch/arm/mach-s5pc100/include/mach/pwm-clock.h new file mode 100644 index 000000000000..b34d2f7aae52 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/pwm-clock.h @@ -0,0 +1,56 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/pwm-clock.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 - pwm clock and timer support + * + * Based on mach-s3c6400/include/mach/pwm-clock.h + */ + +/** + * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk + * @tcfg: The timer TCFG1 register bits shifted down to 0. + * + * Return true if the given configuration from TCFG1 is a TCLK instead + * any of the TDIV clocks. + */ +static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) +{ + return tcfg >= S3C64XX_TCFG1_MUX_TCLK; +} + +/** + * tcfg_to_divisor() - convert tcfg1 setting to a divisor + * @tcfg1: The tcfg1 setting, shifted down. + * + * Get the divisor value for the given tcfg1 setting. We assume the + * caller has already checked to see if this is not a TCLK source. + */ +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) +{ + return 1 << tcfg1; +} + +/** + * pwm_tdiv_has_div1() - does the tdiv setting have a /1 + * + * Return true if we have a /1 in the tdiv setting. + */ +static inline unsigned int pwm_tdiv_has_div1(void) +{ + return 1; +} + +/** + * pwm_tdiv_div_bits() - calculate TCFG1 divisor value. + * @div: The divisor to calculate the bit information for. + * + * Turn a divisor into the necessary bit field for TCFG1. + */ +static inline unsigned long pwm_tdiv_div_bits(unsigned int div) +{ + return ilog2(div); +} + +#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK diff --git a/arch/arm/mach-s5pc100/include/mach/regs-irq.h b/arch/arm/mach-s5pc100/include/mach/regs-irq.h new file mode 100644 index 000000000000..751ac15438c8 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/regs-irq.h @@ -0,0 +1,24 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/regs-irq.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC1XX - IRQ register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_REGS_IRQ_H +#define __ASM_ARCH_REGS_IRQ_H __FILE__ + +#include <mach/map.h> +#include <asm/hardware/vic.h> + +/* interrupt controller */ +#define S5PC1XX_VIC0REG(x) ((x) + S5PC1XX_VA_VIC(0)) +#define S5PC1XX_VIC1REG(x) ((x) + S5PC1XX_VA_VIC(1)) +#define S5PC1XX_VIC2REG(x) ((x) + S5PC1XX_VA_VIC(2)) + +#endif /* __ASM_ARCH_REGS_IRQ_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/system.h b/arch/arm/mach-s5pc100/include/mach/system.h new file mode 100644 index 000000000000..e39014375470 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/system.h @@ -0,0 +1,24 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/system.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC1XX - system implementation + * + * Based on mach-s3c6400/include/mach/system.h + */ + +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H __FILE__ + +static void arch_idle(void) +{ + /* nothing here yet */ +} + +static void arch_reset(char mode, const char *cmd) +{ + /* nothing here yet */ +} + +#endif /* __ASM_ARCH_IRQ_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/tick.h b/arch/arm/mach-s5pc100/include/mach/tick.h new file mode 100644 index 000000000000..d3de0f3591ae --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/tick.h @@ -0,0 +1,29 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/tick.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S3C64XX - Timer tick support definitions + * + * Based on mach-s3c6400/include/mach/tick.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_TICK_H +#define __ASM_ARCH_TICK_H __FILE__ + +/* note, the timer interrutps turn up in 2 places, the vic and then + * the timer block. We take the VIC as the base at the moment. + */ +static inline u32 s3c24xx_ostimer_pending(void) +{ + u32 pend = __raw_readl(S3C_VA_VIC0 + VIC_RAW_STATUS); + return pend & 1 << (IRQ_TIMER4 - S5PC1XX_IRQ_VIC0(0)); +} + +#define TICK_MAX (0xffffffff) + +#endif /* __ASM_ARCH_TICK_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/uncompress.h b/arch/arm/mach-s5pc100/include/mach/uncompress.h new file mode 100644 index 000000000000..01ccf535e76c --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/uncompress.h @@ -0,0 +1,28 @@ +/* arch/arm/mach-s5pc100/include/mach/uncompress.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 - uncompress code + * + * Based on mach-s3c6400/include/mach/uncompress.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#include <mach/map.h> +#include <plat/uncompress.h> + +static void arch_detect_cpu(void) +{ + /* we do not need to do any cpu detection here at the moment. */ + fifo_mask = S3C2440_UFSTAT_TXMASK; + fifo_max = 63 << S3C2440_UFSTAT_TXSHIFT; +} + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c new file mode 100644 index 000000000000..214093cd7632 --- /dev/null +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -0,0 +1,103 @@ +/* linux/arch/arm/mach-s5pc100/mach-smdkc100.c + * + * Copyright 2009 Samsung Electronics Co. + * Author: Byungho Min <bhmin@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/fb.h> +#include <linux/delay.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <mach/map.h> + +#include <asm/irq.h> +#include <asm/mach-types.h> + +#include <plat/regs-serial.h> + +#include <plat/clock.h> +#include <plat/devs.h> +#include <plat/cpu.h> +#include <plat/s5pc100.h> + +#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK) +#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB) +#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE) + +static struct s3c2410_uartcfg smdkc100_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + [2] = { + .hwport = 2, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + [3] = { + .hwport = 3, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, +}; + +static struct map_desc smdkc100_iodesc[] = {}; + +static struct platform_device *smdkc100_devices[] __initdata = { +}; + +static void __init smdkc100_map_io(void) +{ + s5pc1xx_init_io(smdkc100_iodesc, ARRAY_SIZE(smdkc100_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(smdkc100_uartcfgs, ARRAY_SIZE(smdkc100_uartcfgs)); +} + +static void __init smdkc100_machine_init(void) +{ + platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices)); +} + +MACHINE_START(SMDKC100, "SMDKC100") + /* Maintainer: Byungho Min <bhmin@samsung.com> */ + .phys_io = S5PC1XX_PA_UART & 0xfff00000, + .io_pg_offst = (((u32)S5PC1XX_VA_UART) >> 18) & 0xfffc, + .boot_params = S5PC100_PA_SDRAM + 0x100, + + .init_irq = s5pc100_init_irq, + .map_io = smdkc100_map_io, + .init_machine = smdkc100_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 89b3ccf35e1b..7936085dd758 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -455,8 +455,8 @@ void __init u300_init_irq(void) for (i = 0; i < NR_IRQS; i++) set_bit(i, (unsigned long *) &mask[0]); u300_enable_intcon_clock(); - vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], 0); - vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], 0); + vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]); + vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]); } diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index afc0f87f3fa4..975eae41ee66 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -343,8 +343,7 @@ static struct platform_device versatile_i2c_device = { static struct i2c_board_info versatile_i2c_board_info[] = { { - I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1), - .type = "ds1338", + I2C_BOARD_INFO("ds1338", 0xd0 >> 1), }, }; diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 83c025e72ceb..5fe595aeba69 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -758,7 +758,7 @@ config CACHE_FEROCEON_L2_WRITETHROUGH config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ - REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX + REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK default y select OUTER_CACHE help diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 03cd27d917b9..b270d6228fe2 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -159,7 +159,9 @@ union offset_union { #define __get8_unaligned_check(ins,val,addr,err) \ __asm__( \ - "1: "ins" %1, [%2], #1\n" \ + ARM( "1: "ins" %1, [%2], #1\n" ) \ + THUMB( "1: "ins" %1, [%2]\n" ) \ + THUMB( " add %2, %2, #1\n" ) \ "2:\n" \ " .section .fixup,\"ax\"\n" \ " .align 2\n" \ @@ -215,7 +217,9 @@ union offset_union { do { \ unsigned int err = 0, v = val, a = addr; \ __asm__( FIRST_BYTE_16 \ - "1: "ins" %1, [%2], #1\n" \ + ARM( "1: "ins" %1, [%2], #1\n" ) \ + THUMB( "1: "ins" %1, [%2]\n" ) \ + THUMB( " add %2, %2, #1\n" ) \ " mov %1, %1, "NEXT_BYTE"\n" \ "2: "ins" %1, [%2]\n" \ "3:\n" \ @@ -245,11 +249,17 @@ union offset_union { do { \ unsigned int err = 0, v = val, a = addr; \ __asm__( FIRST_BYTE_32 \ - "1: "ins" %1, [%2], #1\n" \ + ARM( "1: "ins" %1, [%2], #1\n" ) \ + THUMB( "1: "ins" %1, [%2]\n" ) \ + THUMB( " add %2, %2, #1\n" ) \ " mov %1, %1, "NEXT_BYTE"\n" \ - "2: "ins" %1, [%2], #1\n" \ + ARM( "2: "ins" %1, [%2], #1\n" ) \ + THUMB( "2: "ins" %1, [%2]\n" ) \ + THUMB( " add %2, %2, #1\n" ) \ " mov %1, %1, "NEXT_BYTE"\n" \ - "3: "ins" %1, [%2], #1\n" \ + ARM( "3: "ins" %1, [%2], #1\n" ) \ + THUMB( "3: "ins" %1, [%2]\n" ) \ + THUMB( " add %2, %2, #1\n" ) \ " mov %1, %1, "NEXT_BYTE"\n" \ "4: "ins" %1, [%2]\n" \ "5:\n" \ diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index be93ff02a98d..bda0ec31a4e2 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -21,7 +21,7 @@ * * Flush the whole D-cache. * - * Corrupted registers: r0-r5, r7, r9-r11 + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) * * - mm - mm_struct describing address space */ @@ -51,8 +51,12 @@ loop1: loop2: mov r9, r4 @ create working copy of max way size loop3: - orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 - orr r11, r11, r7, lsl r2 @ factor index number into r11 + ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 + THUMB( lsl r6, r9, r5 ) + THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 + ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r7, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way subs r9, r9, #1 @ decrement the way bge loop3 @@ -82,11 +86,13 @@ ENDPROC(v7_flush_dcache_all) * */ ENTRY(v7_flush_kern_cache_all) - stmfd sp!, {r4-r5, r7, r9-r11, lr} + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) bl v7_flush_dcache_all mov r0, #0 mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate - ldmfd sp!, {r4-r5, r7, r9-r11, lr} + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) mov pc, lr ENDPROC(v7_flush_kern_cache_all) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 510c179b0ac8..b30925fcbcdc 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -36,7 +36,34 @@ #define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) #define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) +static u64 get_coherent_dma_mask(struct device *dev) +{ + u64 mask = ISA_DMA_THRESHOLD; + + if (dev) { + mask = dev->coherent_dma_mask; + + /* + * Sanity check the DMA mask - it must be non-zero, and + * must be able to be satisfied by a DMA allocation. + */ + if (mask == 0) { + dev_warn(dev, "coherent DMA mask is unset\n"); + return 0; + } + + if ((~mask) & ISA_DMA_THRESHOLD) { + dev_warn(dev, "coherent DMA mask %#llx is smaller " + "than system GFP_DMA mask %#llx\n", + mask, (unsigned long long)ISA_DMA_THRESHOLD); + return 0; + } + } + return mask; +} + +#ifdef CONFIG_MMU /* * These are the page tables (2MB each) covering uncached, DMA consistent allocations */ @@ -152,7 +179,8 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, struct page *page; struct arm_vm_region *c; unsigned long order; - u64 mask = ISA_DMA_THRESHOLD, limit; + u64 mask = get_coherent_dma_mask(dev); + u64 limit; if (!consistent_pte[0]) { printk(KERN_ERR "%s: not initialised\n", __func__); @@ -160,25 +188,8 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, return NULL; } - if (dev) { - mask = dev->coherent_dma_mask; - - /* - * Sanity check the DMA mask - it must be non-zero, and - * must be able to be satisfied by a DMA allocation. - */ - if (mask == 0) { - dev_warn(dev, "coherent DMA mask is unset\n"); - goto no_page; - } - - if ((~mask) & ISA_DMA_THRESHOLD) { - dev_warn(dev, "coherent DMA mask %#llx is smaller " - "than system GFP_DMA mask %#llx\n", - mask, (unsigned long long)ISA_DMA_THRESHOLD); - goto no_page; - } - } + if (!mask) + goto no_page; /* * Sanity check the allocation size. @@ -267,6 +278,31 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, *handle = ~0; return NULL; } +#else /* !CONFIG_MMU */ +static void * +__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp, + pgprot_t prot) +{ + void *virt; + u64 mask = get_coherent_dma_mask(dev); + + if (!mask) + goto error; + + if (mask != 0xffffffff) + gfp |= GFP_DMA; + virt = kmalloc(size, gfp); + if (!virt) + goto error; + + *handle = virt_to_dma(dev, virt); + return virt; + +error: + *handle = ~0; + return NULL; +} +#endif /* CONFIG_MMU */ /* * Allocate DMA-coherent memory space and return both the kernel remapped @@ -311,9 +347,10 @@ EXPORT_SYMBOL(dma_alloc_writecombine); static int dma_mmap(struct device *dev, struct vm_area_struct *vma, void *cpu_addr, dma_addr_t dma_addr, size_t size) { + int ret = -ENXIO; +#ifdef CONFIG_MMU unsigned long flags, user_size, kern_size; struct arm_vm_region *c; - int ret = -ENXIO; user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; @@ -334,6 +371,7 @@ static int dma_mmap(struct device *dev, struct vm_area_struct *vma, vma->vm_page_prot); } } +#endif /* CONFIG_MMU */ return ret; } @@ -358,6 +396,7 @@ EXPORT_SYMBOL(dma_mmap_writecombine); * free a page as defined by the above mapping. * Must not be called with IRQs disabled. */ +#ifdef CONFIG_MMU void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle) { struct arm_vm_region *c; @@ -444,6 +483,14 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr __func__, cpu_addr); dump_stack(); } +#else /* !CONFIG_MMU */ +void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle) +{ + if (dma_release_from_coherent(dev, get_order(size), cpu_addr)) + return; + kfree(cpu_addr); +} +#endif /* CONFIG_MMU */ EXPORT_SYMBOL(dma_free_coherent); /* @@ -451,10 +498,12 @@ EXPORT_SYMBOL(dma_free_coherent); */ static int __init consistent_init(void) { + int ret = 0; +#ifdef CONFIG_MMU pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int ret = 0, i = 0; + int i = 0; u32 base = CONSISTENT_BASE; do { @@ -477,6 +526,7 @@ static int __init consistent_init(void) consistent_pte[i++] = pte; base += (1 << PGDIR_SHIFT); } while (base < CONSISTENT_END); +#endif /* !CONFIG_MMU */ return ret; } diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 5fa8dea5a371..cc8829d7e116 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -16,6 +16,7 @@ #include <linux/kprobes.h> #include <linux/uaccess.h> #include <linux/page-flags.h> +#include <linux/sched.h> #include <linux/highmem.h> #include <asm/system.h> @@ -24,6 +25,7 @@ #include "fault.h" +#ifdef CONFIG_MMU #ifdef CONFIG_KPROBES static inline int notify_page_fault(struct pt_regs *regs, unsigned int fsr) @@ -98,6 +100,10 @@ void show_pte(struct mm_struct *mm, unsigned long addr) printk("\n"); } +#else /* CONFIG_MMU */ +void show_pte(struct mm_struct *mm, unsigned long addr) +{ } +#endif /* CONFIG_MMU */ /* * Oops. The kernel tried to access some page that wasn't present. @@ -172,6 +178,7 @@ void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs) __do_kernel_fault(mm, addr, fsr, regs); } +#ifdef CONFIG_MMU #define VM_FAULT_BADMAP 0x010000 #define VM_FAULT_BADACCESS 0x020000 @@ -323,6 +330,13 @@ no_context: __do_kernel_fault(mm, addr, fsr, regs); return 0; } +#else /* CONFIG_MMU */ +static int +do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) +{ + return 0; +} +#endif /* CONFIG_MMU */ /* * First Level Translation Fault Handler @@ -341,6 +355,7 @@ no_context: * interrupt or a critical region, and should only copy the information * from the master page table, nothing more. */ +#ifdef CONFIG_MMU static int __kprobes do_translation_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) @@ -379,6 +394,14 @@ bad_area: do_bad_area(addr, fsr, regs); return 0; } +#else /* CONFIG_MMU */ +static int +do_translation_fault(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) +{ + return 0; +} +#endif /* CONFIG_MMU */ /* * Some section permission faults need to be handled gracefully. diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index ad7bacc693b2..900811cc9130 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -12,6 +12,7 @@ #include <asm/cacheflush.h> #include <asm/sections.h> #include <asm/page.h> +#include <asm/setup.h> #include <asm/mach/arch.h> #include "mm.h" diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index a0b3f36f3178..7d63beaf9745 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -77,6 +77,7 @@ * Sanity check the PTE configuration for the code below - which makes * certain assumptions about how these bits are layed out. */ +#ifdef CONFIG_MMU #if L_PTE_SHARED != PTE_EXT_SHARED #error PTE shared bit mismatch #endif @@ -84,6 +85,7 @@ L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED #error Invalid Linux PTE bit settings #endif +#endif /* CONFIG_MMU */ /* * The ARMv6 and ARMv7 set_pte_ext translation function. diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 180a08d03a03..f3fa1c32fe92 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -127,7 +127,9 @@ ENDPROC(cpu_v7_switch_mm) */ ENTRY(cpu_v7_set_pte_ext) #ifdef CONFIG_MMU - str r1, [r0], #-2048 @ linux version + ARM( str r1, [r0], #-2048 ) @ linux version + THUMB( str r1, [r0] ) @ linux version + THUMB( sub r0, r0, #2048 ) bic r3, r1, #0x000003f0 bic r3, r3, #PTE_TYPE_MASK @@ -232,7 +234,6 @@ __v7_setup: mcr p15, 0, r4, c2, c0, 1 @ load TTB1 mov r10, #0x1f @ domains 0, 1 = manager mcr p15, 0, r10, c3, c0, 0 @ load domain access register -#endif /* * Memory region attributes with SCTLR.TRE=1 * @@ -265,6 +266,7 @@ __v7_setup: ldr r6, =0x40e040e0 @ NMRR mcr p15, 0, r5, c10, c2, 0 @ write PRRR mcr p15, 0, r6, c10, c2, 1 @ write NMRR +#endif adr r5, v7_crval ldmia r5, {r5, r6} #ifdef CONFIG_CPU_ENDIAN_BE8 @@ -273,6 +275,7 @@ __v7_setup: mrc p15, 0, r0, c1, c0, 0 @ read control register bic r0, r0, r5 @ clear bits them orr r0, r0, r6 @ set them + THUMB( orr r0, r0, #1 << 30 ) @ Thumb exceptions mov pc, lr @ return to head.S:__ret ENDPROC(__v7_setup) diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig index 8986b7412235..ca5c7c226341 100644 --- a/arch/arm/plat-mxc/Kconfig +++ b/arch/arm/plat-mxc/Kconfig @@ -9,6 +9,7 @@ choice config ARCH_MX1 bool "MX1-based" select CPU_ARM920T + select COMMON_CLKDEV help This enables support for systems based on the Freescale i.MX1 family @@ -19,6 +20,13 @@ config ARCH_MX2 help This enables support for systems based on the Freescale i.MX2 family +config ARCH_MX25 + bool "MX25-based" + select CPU_ARM926T + select COMMON_CLKDEV + help + This enables support for systems based on the Freescale i.MX25 family + config ARCH_MX3 bool "MX3-based" select CPU_V6 @@ -26,11 +34,20 @@ config ARCH_MX3 help This enables support for systems based on the Freescale i.MX3 family +config ARCH_MXC91231 + bool "MXC91231-based" + select CPU_V6 + select COMMON_CLKDEV + help + This enables support for systems based on the Freescale MXC91231 family + endchoice source "arch/arm/mach-mx1/Kconfig" source "arch/arm/mach-mx2/Kconfig" source "arch/arm/mach-mx3/Kconfig" +source "arch/arm/mach-mx25/Kconfig" +source "arch/arm/mach-mxc91231/Kconfig" endmenu diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c index 92e13566cd4f..9e8fbd57495c 100644 --- a/arch/arm/plat-mxc/clock.c +++ b/arch/arm/plat-mxc/clock.c @@ -39,6 +39,7 @@ #include <linux/string.h> #include <mach/clock.h> +#include <mach/hardware.h> static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); @@ -47,76 +48,6 @@ static DEFINE_MUTEX(clocks_mutex); * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ -/* - * All the code inside #ifndef CONFIG_COMMON_CLKDEV can be removed once all - * MXC architectures have switched to using clkdev. - */ -#ifndef CONFIG_COMMON_CLKDEV -/* - * Retrieve a clock by name. - * - * Note that we first try to use device id on the bus - * and clock name. If this fails, we try to use "<name>.<id>". If this fails, - * we try to use clock name only. - * The reference count to the clock's module owner ref count is incremented. - */ -struct clk *clk_get(struct device *dev, const char *id) -{ - struct clk *p, *clk = ERR_PTR(-ENOENT); - int idno; - const char *str; - - if (id == NULL) - return clk; - - if (dev == NULL || dev->bus != &platform_bus_type) - idno = -1; - else - idno = to_platform_device(dev)->id; - - mutex_lock(&clocks_mutex); - - list_for_each_entry(p, &clocks, node) { - if (p->id == idno && - strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - goto found; - } - } - - str = strrchr(id, '.'); - if (str) { - int cnt = str - id; - str++; - idno = simple_strtol(str, NULL, 10); - list_for_each_entry(p, &clocks, node) { - if (p->id == idno && - strlen(p->name) == cnt && - strncmp(id, p->name, cnt) == 0 && - try_module_get(p->owner)) { - clk = p; - goto found; - } - } - } - - list_for_each_entry(p, &clocks, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - goto found; - } - } - - printk(KERN_WARNING "clk: Unable to get requested clock: %s\n", id); - -found: - mutex_unlock(&clocks_mutex); - - return clk; -} -EXPORT_SYMBOL(clk_get); -#endif - static void __clk_disable(struct clk *clk) { if (clk == NULL || IS_ERR(clk)) @@ -193,16 +124,6 @@ unsigned long clk_get_rate(struct clk *clk) } EXPORT_SYMBOL(clk_get_rate); -#ifndef CONFIG_COMMON_CLKDEV -/* Decrement the clock's module reference count */ -void clk_put(struct clk *clk) -{ - if (clk && !IS_ERR(clk)) - module_put(clk->owner); -} -EXPORT_SYMBOL(clk_put); -#endif - /* Round the requested clock rate to the nearest supported * rate that is less than or equal to the requested rate. * This is dependent on the clock's current parent. @@ -265,80 +186,6 @@ struct clk *clk_get_parent(struct clk *clk) } EXPORT_SYMBOL(clk_get_parent); -#ifndef CONFIG_COMMON_CLKDEV -/* - * Add a new clock to the clock tree. - */ -int clk_register(struct clk *clk) -{ - if (clk == NULL || IS_ERR(clk)) - return -EINVAL; - - mutex_lock(&clocks_mutex); - list_add(&clk->node, &clocks); - mutex_unlock(&clocks_mutex); - - return 0; -} -EXPORT_SYMBOL(clk_register); - -/* Remove a clock from the clock tree */ -void clk_unregister(struct clk *clk) -{ - if (clk == NULL || IS_ERR(clk)) - return; - - mutex_lock(&clocks_mutex); - list_del(&clk->node); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL(clk_unregister); - -#ifdef CONFIG_PROC_FS -static int mxc_clock_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct clk *clkp; - char *p = page; - int len; - - list_for_each_entry(clkp, &clocks, node) { - p += sprintf(p, "%s-%d:\t\t%lu, %d", clkp->name, clkp->id, - clk_get_rate(clkp), clkp->usecount); - if (clkp->parent) - p += sprintf(p, ", %s-%d\n", clkp->parent->name, - clkp->parent->id); - else - p += sprintf(p, "\n"); - } - - len = (p - page) - off; - if (len < 0) - len = 0; - - *eof = (len <= count) ? 1 : 0; - *start = page + off; - - return len; -} - -static int __init mxc_setup_proc_entry(void) -{ - struct proc_dir_entry *res; - - res = create_proc_read_entry("cpu/clocks", 0, NULL, - mxc_clock_read_proc, NULL); - if (!res) { - printk(KERN_ERR "Failed to create proc/cpu/clocks\n"); - return -ENOMEM; - } - return 0; -} - -late_initcall(mxc_setup_proc_entry); -#endif /* CONFIG_PROC_FS */ -#endif - /* * Get the resulting clock rate from a PLL register value and the input * frequency. PLLs with this register layout can at least be found on @@ -363,12 +210,11 @@ unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq) mfn_abs = mfn; -#if !defined CONFIG_ARCH_MX1 && !defined CONFIG_ARCH_MX21 - if (mfn >= 0x200) { - mfn |= 0xFFFFFE00; - mfn_abs = -mfn; - } -#endif + /* On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit + * 2's complements number + */ + if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200) + mfn_abs = 0x400 - mfn; freq *= 2; freq /= pd + 1; @@ -376,8 +222,10 @@ unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq) ll = (unsigned long long)freq * mfn_abs; do_div(ll, mfd + 1); - if (mfn < 0) + + if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200) ll = -ll; + ll = (freq * mfi) + ll; return ll; diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c index 7506d963be4b..cfc4a8b43e6a 100644 --- a/arch/arm/plat-mxc/gpio.c +++ b/arch/arm/plat-mxc/gpio.c @@ -29,6 +29,23 @@ static struct mxc_gpio_port *mxc_gpio_ports; static int gpio_table_size; +#define cpu_is_mx1_mx2() (cpu_is_mx1() || cpu_is_mx2()) + +#define GPIO_DR (cpu_is_mx1_mx2() ? 0x1c : 0x00) +#define GPIO_GDIR (cpu_is_mx1_mx2() ? 0x00 : 0x04) +#define GPIO_PSR (cpu_is_mx1_mx2() ? 0x24 : 0x08) +#define GPIO_ICR1 (cpu_is_mx1_mx2() ? 0x28 : 0x0C) +#define GPIO_ICR2 (cpu_is_mx1_mx2() ? 0x2C : 0x10) +#define GPIO_IMR (cpu_is_mx1_mx2() ? 0x30 : 0x14) +#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18) +#define GPIO_ISR (cpu_is_mx1_mx2() ? 0x34 : 0x18) + +#define GPIO_INT_LOW_LEV (cpu_is_mx1_mx2() ? 0x3 : 0x0) +#define GPIO_INT_HIGH_LEV (cpu_is_mx1_mx2() ? 0x2 : 0x1) +#define GPIO_INT_RISE_EDGE (cpu_is_mx1_mx2() ? 0x0 : 0x2) +#define GPIO_INT_FALL_EDGE (cpu_is_mx1_mx2() ? 0x1 : 0x3) +#define GPIO_INT_NONE 0x4 + /* Note: This driver assumes 32 GPIOs are handled in one register */ static void _clear_gpio_irqstatus(struct mxc_gpio_port *port, u32 index) @@ -162,7 +179,6 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) } } -#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX1) /* MX1 and MX3 has one interrupt *per* gpio port */ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) { @@ -174,9 +190,7 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc) mxc_gpio_irq_handler(port, irq_stat); } -#endif -#ifdef CONFIG_ARCH_MX2 /* MX2 has one interrupt *for all* gpio ports */ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) { @@ -195,7 +209,6 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) mxc_gpio_irq_handler(&port[i], irq_stat); } } -#endif static struct irq_chip gpio_irq_chip = { .ack = gpio_ack_irq, @@ -284,17 +297,18 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt) /* its a serious configuration bug when it fails */ BUG_ON( gpiochip_add(&port[i].chip) < 0 ); -#if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX1) - /* setup one handler for each entry */ - set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler); - set_irq_data(port[i].irq, &port[i]); -#endif + if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25()) { + /* setup one handler for each entry */ + set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler); + set_irq_data(port[i].irq, &port[i]); + } + } + + if (cpu_is_mx2()) { + /* setup one handler for all GPIO interrupts */ + set_irq_chained_handler(port[0].irq, mx2_gpio_irq_handler); + set_irq_data(port[0].irq, port); } -#ifdef CONFIG_ARCH_MX2 - /* setup one handler for all GPIO interrupts */ - set_irq_chained_handler(port[0].irq, mx2_gpio_irq_handler); - set_irq_data(port[0].irq, port); -#endif return 0; } diff --git a/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h b/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h index 8769e910e559..0376c133c9f4 100644 --- a/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h +++ b/arch/arm/plat-mxc/include/mach/board-armadillo5x0.h @@ -12,11 +12,4 @@ #ifndef __ASM_ARCH_MXC_BOARD_ARMADILLO5X0_H__ #define __ASM_ARCH_MXC_BOARD_ARMADILLO5X0_H__ -#include <mach/hardware.h> - -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif diff --git a/arch/arm/plat-mxc/include/mach/board-eukrea_cpuimx27.h b/arch/arm/plat-mxc/include/mach/board-eukrea_cpuimx27.h new file mode 100644 index 000000000000..a1fd5830af48 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/board-eukrea_cpuimx27.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 Eric Benard - eric@eukrea.com + * + * Based on board-pcm038.h which is : + * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#ifndef __ASM_ARCH_MXC_BOARD_EUKREA_CPUIMX27_H__ +#define __ASM_ARCH_MXC_BOARD_EUKREA_CPUIMX27_H__ + +#ifndef __ASSEMBLY__ +/* + * This CPU module needs a baseboard to work. After basic initializing + * its own devices, it calls baseboard's init function. + * TODO: Add your own baseboard init function and call it from + * inside eukrea_cpuimx27_init(). + * + * This example here is for the development board. Refer + * eukrea_mbimx27-baseboard.c + */ + +extern void eukrea_mbimx27_baseboard_init(void); + +#endif + +#endif /* __ASM_ARCH_MXC_BOARD_EUKREA_CPUIMX27_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-mx21ads.h b/arch/arm/plat-mxc/include/mach/board-mx21ads.h index 06701df74c42..0cf4fa29510c 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx21ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx21ads.h @@ -15,12 +15,6 @@ #define __ASM_ARCH_MXC_BOARD_MX21ADS_H__ /* - * MXC UART EVB board level configurations - */ -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPI_IO_ADDRESS(UART1_BASE_ADDR) - -/* * Memory-mapped I/O on MX21ADS base board */ #define MX21ADS_MMIO_BASE_ADDR 0xF5000000 diff --git a/arch/arm/plat-mxc/include/mach/board-mx27ads.h b/arch/arm/plat-mxc/include/mach/board-mx27ads.h index d42f4e6116f8..7776d230327f 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx27ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx27ads.h @@ -26,12 +26,6 @@ MXC_MAX_VIRTUAL_INTS) /* - * MXC UART EVB board level configurations - */ -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPI_IO_ADDRESS(UART1_BASE_ADDR) - -/* * @name Memory Size parameters */ diff --git a/arch/arm/plat-mxc/include/mach/board-mx27lite.h b/arch/arm/plat-mxc/include/mach/board-mx27lite.h index a870f8ea2443..ea87551d2736 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx27lite.h +++ b/arch/arm/plat-mxc/include/mach/board-mx27lite.h @@ -11,9 +11,4 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX27LITE_H__ #define __ASM_ARCH_MXC_BOARD_MX27LITE_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_BOARD_MX27LITE_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-mx27pdk.h b/arch/arm/plat-mxc/include/mach/board-mx27pdk.h index 552b55d714d8..fec1bcfa9164 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx27pdk.h +++ b/arch/arm/plat-mxc/include/mach/board-mx27pdk.h @@ -11,9 +11,4 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX27PDK_H__ #define __ASM_ARCH_MXC_BOARD_MX27PDK_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_BOARD_MX27PDK_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-mx31ads.h b/arch/arm/plat-mxc/include/mach/board-mx31ads.h index 06e6895f7f65..2cbfa35e82ff 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx31ads.h +++ b/arch/arm/plat-mxc/include/mach/board-mx31ads.h @@ -114,9 +114,4 @@ #define MXC_MAX_EXP_IO_LINES 16 -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_BOARD_MX31ADS_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-mx31lilly.h b/arch/arm/plat-mxc/include/mach/board-mx31lilly.h index 78cf31e22e4d..eb5a5024622e 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx31lilly.h +++ b/arch/arm/plat-mxc/include/mach/board-mx31lilly.h @@ -22,11 +22,6 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX31LILLY_H__ #define __ASM_ARCH_MXC_BOARD_MX31LILLY_H__ -/* mandatory for CONFIG_LL_DEBUG */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR (AIPI_BASE_ADDR_VIRT + 0x0A000) - #ifndef __ASSEMBLY__ enum mx31lilly_boards { diff --git a/arch/arm/plat-mxc/include/mach/board-mx31lite.h b/arch/arm/plat-mxc/include/mach/board-mx31lite.h index 52fbdf2d6f26..8e64325d6905 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx31lite.h +++ b/arch/arm/plat-mxc/include/mach/board-mx31lite.h @@ -11,8 +11,5 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX31LITE_H__ #define __ASM_ARCH_MXC_BOARD_MX31LITE_H__ -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_BOARD_MX31LITE_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h index 303fd2434a21..d5be6b5a6acf 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx31moboard.h +++ b/arch/arm/plat-mxc/include/mach/board-mx31moboard.h @@ -19,11 +19,6 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ #define __ASM_ARCH_MXC_BOARD_MX31MOBOARD_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR (AIPI_BASE_ADDR_VIRT + 0x0A000) - #ifndef __ASSEMBLY__ enum mx31moboard_boards { diff --git a/arch/arm/plat-mxc/include/mach/board-mx31pdk.h b/arch/arm/plat-mxc/include/mach/board-mx31pdk.h index 519bab3eb28b..2bbd6ed17f50 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx31pdk.h +++ b/arch/arm/plat-mxc/include/mach/board-mx31pdk.h @@ -11,11 +11,6 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX31PDK_H__ #define __ASM_ARCH_MXC_BOARD_MX31PDK_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - /* Definitions for components on the Debug board */ /* Base address of CPLD controller on the Debug board */ diff --git a/arch/arm/plat-mxc/include/mach/board-mx35pdk.h b/arch/arm/plat-mxc/include/mach/board-mx35pdk.h index 1111037d6d9d..383f1c04df06 100644 --- a/arch/arm/plat-mxc/include/mach/board-mx35pdk.h +++ b/arch/arm/plat-mxc/include/mach/board-mx35pdk.h @@ -19,9 +19,4 @@ #ifndef __ASM_ARCH_MXC_BOARD_MX35PDK_H__ #define __ASM_ARCH_MXC_BOARD_MX35PDK_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_BOARD_MX35PDK_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-pcm037.h b/arch/arm/plat-mxc/include/mach/board-pcm037.h index f0a1fa1938a2..13411709b13a 100644 --- a/arch/arm/plat-mxc/include/mach/board-pcm037.h +++ b/arch/arm/plat-mxc/include/mach/board-pcm037.h @@ -19,9 +19,4 @@ #ifndef __ASM_ARCH_MXC_BOARD_PCM037_H__ #define __ASM_ARCH_MXC_BOARD_PCM037_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_BOARD_PCM037_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-pcm038.h b/arch/arm/plat-mxc/include/mach/board-pcm038.h index 4fcd7499e092..410f9786ed22 100644 --- a/arch/arm/plat-mxc/include/mach/board-pcm038.h +++ b/arch/arm/plat-mxc/include/mach/board-pcm038.h @@ -19,11 +19,6 @@ #ifndef __ASM_ARCH_MXC_BOARD_PCM038_H__ #define __ASM_ARCH_MXC_BOARD_PCM038_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR (AIPI_BASE_ADDR_VIRT + 0x0A000) - #ifndef __ASSEMBLY__ /* * This CPU module needs a baseboard to work. After basic initializing diff --git a/arch/arm/plat-mxc/include/mach/board-pcm043.h b/arch/arm/plat-mxc/include/mach/board-pcm043.h index 15fbdf16abcd..1ac4e1682e5c 100644 --- a/arch/arm/plat-mxc/include/mach/board-pcm043.h +++ b/arch/arm/plat-mxc/include/mach/board-pcm043.h @@ -19,9 +19,4 @@ #ifndef __ASM_ARCH_MXC_BOARD_PCM043_H__ #define __ASM_ARCH_MXC_BOARD_PCM043_H__ -/* mandatory for CONFIG_LL_DEBUG */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_BOARD_PCM043_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/board-qong.h b/arch/arm/plat-mxc/include/mach/board-qong.h index 04033ec637d2..6d88c7af4b23 100644 --- a/arch/arm/plat-mxc/include/mach/board-qong.h +++ b/arch/arm/plat-mxc/include/mach/board-qong.h @@ -11,11 +11,6 @@ #ifndef __ASM_ARCH_MXC_BOARD_QONG_H__ #define __ASM_ARCH_MXC_BOARD_QONG_H__ -/* mandatory for CONFIG_DEBUG_LL */ - -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) - /* NOR FLASH */ #define QONG_NOR_SIZE (128*1024*1024) diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h index 02c3cd004db3..286cb9b0a25b 100644 --- a/arch/arm/plat-mxc/include/mach/common.h +++ b/arch/arm/plat-mxc/include/mach/common.h @@ -16,18 +16,33 @@ struct clk; extern void mx1_map_io(void); extern void mx21_map_io(void); +extern void mx25_map_io(void); extern void mx27_map_io(void); extern void mx31_map_io(void); extern void mx35_map_io(void); -extern void mxc_init_irq(void); -extern void mxc_timer_init(struct clk *timer_clk); +extern void mxc91231_map_io(void); +extern void mxc_init_irq(void __iomem *); +extern void mx1_init_irq(void); +extern void mx21_init_irq(void); +extern void mx25_init_irq(void); +extern void mx27_init_irq(void); +extern void mx31_init_irq(void); +extern void mx35_init_irq(void); +extern void mxc91231_init_irq(void); +extern void mxc_timer_init(struct clk *timer_clk, void __iomem *, int); extern int mx1_clocks_init(unsigned long fref); extern int mx21_clocks_init(unsigned long lref, unsigned long fref); +extern int mx25_clocks_init(unsigned long fref); extern int mx27_clocks_init(unsigned long fref); extern int mx31_clocks_init(unsigned long fref); extern int mx35_clocks_init(void); +extern int mxc91231_clocks_init(unsigned long fref); extern int mxc_register_gpios(void); extern int mxc_register_device(struct platform_device *pdev, void *data); extern void mxc_set_cpu_type(unsigned int type); +extern void mxc_arch_reset_init(void __iomem *); +extern void mxc91231_power_off(void); +extern void mxc91231_arch_reset(int, const char *); +extern void mxc91231_prepare_idle(void); #endif diff --git a/arch/arm/plat-mxc/include/mach/debug-macro.S b/arch/arm/plat-mxc/include/mach/debug-macro.S index bbc5f6753cfb..15b2b148a105 100644 --- a/arch/arm/plat-mxc/include/mach/debug-macro.S +++ b/arch/arm/plat-mxc/include/mach/debug-macro.S @@ -11,52 +11,52 @@ * */ -#include <mach/hardware.h> - -#ifdef CONFIG_MACH_MX31ADS -#include <mach/board-mx31ads.h> -#endif -#ifdef CONFIG_MACH_PCM037 -#include <mach/board-pcm037.h> -#endif -#ifdef CONFIG_MACH_MX31LITE -#include <mach/board-mx31lite.h> -#endif -#ifdef CONFIG_MACH_MX27ADS -#include <mach/board-mx27ads.h> -#endif -#ifdef CONFIG_MACH_MX21ADS -#include <mach/board-mx21ads.h> +#ifdef CONFIG_ARCH_MX1 +#include <mach/mx1.h> +#define UART_PADDR UART1_BASE_ADDR +#define UART_VADDR IO_ADDRESS(UART1_BASE_ADDR) #endif -#ifdef CONFIG_MACH_PCM038 -#include <mach/board-pcm038.h> + +#ifdef CONFIG_ARCH_MX25 +#ifdef UART_PADDR +#error "CONFIG_DEBUG_LL is incompatible with multiple archs" #endif -#ifdef CONFIG_MACH_MX31_3DS -#include <mach/board-mx31pdk.h> +#include <mach/mx25.h> +#define UART_PADDR UART1_BASE_ADDR +#define UART_VADDR MX25_AIPS1_IO_ADDRESS(UART1_BASE_ADDR) #endif -#ifdef CONFIG_MACH_QONG -#include <mach/board-qong.h> + +#ifdef CONFIG_ARCH_MX2 +#ifdef UART_PADDR +#error "CONFIG_DEBUG_LL is incompatible with multiple archs" #endif -#ifdef CONFIG_MACH_PCM043 -#include <mach/board-pcm043.h> +#include <mach/mx2x.h> +#define UART_PADDR UART1_BASE_ADDR +#define UART_VADDR AIPI_IO_ADDRESS(UART1_BASE_ADDR) #endif -#ifdef CONFIG_MACH_MX27_3DS -#include <mach/board-mx27pdk.h> + +#ifdef CONFIG_ARCH_MX3 +#ifdef UART_PADDR +#error "CONFIG_DEBUG_LL is incompatible with multiple archs" #endif -#ifdef CONFIG_MACH_ARMADILLO5X0 -#include <mach/board-armadillo5x0.h> +#include <mach/mx3x.h> +#define UART_PADDR UART1_BASE_ADDR +#define UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) #endif -#ifdef CONFIG_MACH_MX35_3DS -#include <mach/board-mx35pdk.h> + +#ifdef CONFIG_ARCH_MXC91231 +#ifdef UART_PADDR +#error "CONFIG_DEBUG_LL is incompatible with multiple archs" #endif -#ifdef CONFIG_MACH_MX27LITE -#include <mach/board-mx27lite.h> +#include <mach/mxc91231.h> +#define UART_PADDR MXC91231_UART2_BASE_ADDR +#define UART_VADDR MXC91231_AIPS1_IO_ADDRESS(MXC91231_UART2_BASE_ADDR) #endif .macro addruart,rx mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? - ldreq \rx, =MXC_LL_UART_PADDR @ physical - ldrne \rx, =MXC_LL_UART_VADDR @ virtual + ldreq \rx, =UART_PADDR @ physical + ldrne \rx, =UART_VADDR @ virtual .endm .macro senduart,rd,rx diff --git a/arch/arm/plat-mxc/include/mach/entry-macro.S b/arch/arm/plat-mxc/include/mach/entry-macro.S index 5f01d60da845..7cf290efe768 100644 --- a/arch/arm/plat-mxc/include/mach/entry-macro.S +++ b/arch/arm/plat-mxc/include/mach/entry-macro.S @@ -18,7 +18,8 @@ .endm .macro get_irqnr_preamble, base, tmp - ldr \base, =AVIC_IO_ADDRESS(AVIC_BASE_ADDR) + ldr \base, =avic_base + ldr \base, [\base] #ifdef CONFIG_MXC_IRQ_PRIOR ldr r4, [\base, #AVIC_NIMASK] #endif diff --git a/arch/arm/plat-mxc/include/mach/hardware.h b/arch/arm/plat-mxc/include/mach/hardware.h index 42e4ee37ca1f..78db75475f69 100644 --- a/arch/arm/plat-mxc/include/mach/hardware.h +++ b/arch/arm/plat-mxc/include/mach/hardware.h @@ -42,6 +42,14 @@ # include <mach/mx1.h> #endif +#ifdef CONFIG_ARCH_MX25 +# include <mach/mx25.h> +#endif + +#ifdef CONFIG_ARCH_MXC91231 +# include <mach/mxc91231.h> +#endif + #include <mach/mxc.h> #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/imxfb.h b/arch/arm/plat-mxc/include/mach/imxfb.h index 9f0101157ec1..5263506b7ddf 100644 --- a/arch/arm/plat-mxc/include/mach/imxfb.h +++ b/arch/arm/plat-mxc/include/mach/imxfb.h @@ -2,6 +2,8 @@ * This structure describes the machine which we are running on. */ +#include <linux/fb.h> + #define PCR_TFT (1 << 31) #define PCR_COLOR (1 << 30) #define PCR_PBSIZ_1 (0 << 28) @@ -13,7 +15,8 @@ #define PCR_BPIX_4 (2 << 25) #define PCR_BPIX_8 (3 << 25) #define PCR_BPIX_12 (4 << 25) -#define PCR_BPIX_16 (4 << 25) +#define PCR_BPIX_16 (5 << 25) +#define PCR_BPIX_18 (6 << 25) #define PCR_PIXPOL (1 << 24) #define PCR_FLMPOL (1 << 23) #define PCR_LPPOL (1 << 22) @@ -46,29 +49,21 @@ #define DMACR_HM(x) (((x) & 0xf) << 16) #define DMACR_TM(x) ((x) & 0xf) -struct imx_fb_platform_data { - u_long pixclock; - - u_short xres; - u_short yres; - - u_int nonstd; - u_char bpp; - u_char hsync_len; - u_char left_margin; - u_char right_margin; +struct imx_fb_videomode { + struct fb_videomode mode; + u32 pcr; + unsigned char bpp; +}; - u_char vsync_len; - u_char upper_margin; - u_char lower_margin; - u_char sync; +struct imx_fb_platform_data { + struct imx_fb_videomode *mode; + int num_modes; u_int cmap_greyscale:1, cmap_inverse:1, cmap_static:1, unused:29; - u_int pcr; u_int pwmr; u_int lscr1; u_int dmacr; diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx25.h b/arch/arm/plat-mxc/include/mach/iomux-mx25.h new file mode 100644 index 000000000000..810c47f56e77 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux-mx25.h @@ -0,0 +1,517 @@ +/* + * arch/arm/plat-mxc/include/mach/iomux-mx25.h + * + * Copyright (C) 2009 by Lothar Wassmann <LW@KARO-electronics.de> + * + * based on arch/arm/mach-mx25/mx25_pins.h + * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. + * and + * arch/arm/plat-mxc/include/mach/iomux-mx35.h + * Copyright (C, NO_PAD_CTRL) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de> + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __IOMUX_MX25_H__ +#define __IOMUX_MX25_H__ + +#include <mach/iomux-v3.h> + +#ifndef GPIO_PORTA +#error Please include mach/iomux.h +#endif + +/* + * + * @brief MX25 I/O Pin List + * + * @ingroup GPIO_MX25 + */ + +#ifndef __ASSEMBLY__ + +/* + * IOMUX/PAD Bit field definitions + */ + +#define MX25_PAD_A10__A10 IOMUX_PAD(0x000, 0x008, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A10__GPIO_4_0 IOMUX_PAD(0x000, 0x008, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A13__A13 IOMUX_PAD(0x22C, 0x00c, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A13__GPIO_4_1 IOMUX_PAD(0x22C, 0x00c, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A14__A14 IOMUX_PAD(0x230, 0x010, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A14__GPIO_2_0 IOMUX_PAD(0x230, 0x010, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A15__A15 IOMUX_PAD(0x234, 0x014, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A15__GPIO_2_1 IOMUX_PAD(0x234, 0x014, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A16__A16 IOMUX_PAD(0x000, 0x018, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A16__GPIO_2_2 IOMUX_PAD(0x000, 0x018, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A17__A17 IOMUX_PAD(0x238, 0x01c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A17__GPIO_2_3 IOMUX_PAD(0x238, 0x01c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A18__A18 IOMUX_PAD(0x23c, 0x020, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A18__GPIO_2_4 IOMUX_PAD(0x23c, 0x020, 0x15, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A18__FEC_COL IOMUX_PAD(0x23c, 0x020, 0x17, 0x504, 0, NO_PAD_CTL) + +#define MX25_PAD_A19__A19 IOMUX_PAD(0x240, 0x024, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A19__FEC_RX_ER IOMUX_PAD(0x240, 0x024, 0x17, 0x518, 0, NO_PAD_CTL) +#define MX25_PAD_A19__GPIO_2_5 IOMUX_PAD(0x240, 0x024, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A20__A20 IOMUX_PAD(0x244, 0x028, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A20__GPIO_2_6 IOMUX_PAD(0x244, 0x028, 0x15, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A20__FEC_RDATA2 IOMUX_PAD(0x244, 0x028, 0x17, 0x50c, 0, NO_PAD_CTL) + +#define MX25_PAD_A21__A21 IOMUX_PAD(0x248, 0x02c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A21__GPIO_2_7 IOMUX_PAD(0x248, 0x02c, 0x15, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A21__FEC_RDATA3 IOMUX_PAD(0x248, 0x02c, 0x17, 0x510, 0, NO_PAD_CTL) + +#define MX25_PAD_A22__A22 IOMUX_PAD(0x000, 0x030, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A22__GPIO_2_8 IOMUX_PAD(0x000, 0x030, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A23__A23 IOMUX_PAD(0x24c, 0x034, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A23__GPIO_2_9 IOMUX_PAD(0x24c, 0x034, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_A24__A24 IOMUX_PAD(0x250, 0x038, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A24__GPIO_2_10 IOMUX_PAD(0x250, 0x038, 0x15, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A24__FEC_RX_CLK IOMUX_PAD(0x250, 0x038, 0x17, 0x514, 0, NO_PAD_CTL) + +#define MX25_PAD_A25__A25 IOMUX_PAD(0x254, 0x03c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A25__GPIO_2_11 IOMUX_PAD(0x254, 0x03c, 0x15, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_A25__FEC_CRS IOMUX_PAD(0x254, 0x03c, 0x17, 0x508, 0, NO_PAD_CTL) + +#define MX25_PAD_EB0__EB0 IOMUX_PAD(0x258, 0x040, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_EB0__AUD4_TXD IOMUX_PAD(0x258, 0x040, 0x14, 0x464, 0, NO_PAD_CTRL) +#define MX25_PAD_EB0__GPIO_2_12 IOMUX_PAD(0x258, 0x040, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_EB1__EB1 IOMUX_PAD(0x25c, 0x044, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_EB1__AUD4_RXD IOMUX_PAD(0x25c, 0x044, 0x14, 0x460, 0, NO_PAD_CTRL) +#define MX25_PAD_EB1__GPIO_2_13 IOMUX_PAD(0x25c, 0x044, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_OE__OE IOMUX_PAD(0x260, 0x048, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_OE__AUD4_TXC IOMUX_PAD(0x260, 0x048, 0x14, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_OE__GPIO_2_14 IOMUX_PAD(0x260, 0x048, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CS0__CS0 IOMUX_PAD(0x000, 0x04c, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CS0__GPIO_4_2 IOMUX_PAD(0x000, 0x04c, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CS1__CS1 IOMUX_PAD(0x000, 0x050, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CS1__GPIO_4_3 IOMUX_PAD(0x000, 0x050, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CS4__CS4 IOMUX_PAD(0x264, 0x054, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CS4__UART5_CTS IOMUX_PAD(0x264, 0x054, 0x13, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CS4__GPIO_3_20 IOMUX_PAD(0x264, 0x054, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CS5__CS5 IOMUX_PAD(0x268, 0x058, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CS5__UART5_RTS IOMUX_PAD(0x268, 0x058, 0x13, 0x574, 0, NO_PAD_CTRL) +#define MX25_PAD_CS5__GPIO_3_21 IOMUX_PAD(0x268, 0x058, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_NF_CE0__NF_CE0 IOMUX_PAD(0x26c, 0x05c, 0x10, 0, 0, NO_PAD_CTL) +#define MX25_PAD_NF_CE0__GPIO_3_22 IOMUX_PAD(0x26c, 0x05c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_ECB__ECB IOMUX_PAD(0x270, 0x060, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_ECB__UART5_TXD_MUX IOMUX_PAD(0x270, 0x060, 0x13, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_ECB__GPIO_3_23 IOMUX_PAD(0x270, 0x060, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LBA__LBA IOMUX_PAD(0x274, 0x064, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LBA__UART5_RXD_MUX IOMUX_PAD(0x274, 0x064, 0x13, 0x578, 0, NO_PAD_CTRL) +#define MX25_PAD_LBA__GPIO_3_24 IOMUX_PAD(0x274, 0x064, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_BCLK__BCLK IOMUX_PAD(0x000, 0x068, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_BCLK__GPIO_4_4 IOMUX_PAD(0x000, 0x068, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_RW__RW IOMUX_PAD(0x278, 0x06c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_RW__AUD4_TXFS IOMUX_PAD(0x278, 0x06c, 0x14, 0x474, 0, NO_PAD_CTRL) +#define MX25_PAD_RW__GPIO_3_25 IOMUX_PAD(0x278, 0x06c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_NFWE_B__NFWE_B IOMUX_PAD(0x000, 0x070, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_NFWE_B__GPIO_3_26 IOMUX_PAD(0x000, 0x070, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_NFRE_B__NFRE_B IOMUX_PAD(0x000, 0x074, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_NFRE_B__GPIO_3_27 IOMUX_PAD(0x000, 0x074, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_NFALE__NFALE IOMUX_PAD(0x000, 0x078, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_NFALE__GPIO_3_28 IOMUX_PAD(0x000, 0x078, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_NFCLE__NFCLE IOMUX_PAD(0x000, 0x07c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_NFCLE__GPIO_3_29 IOMUX_PAD(0x000, 0x07c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_NFWP_B__NFWP_B IOMUX_PAD(0x000, 0x080, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_NFWP_B__GPIO_3_30 IOMUX_PAD(0x000, 0x080, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_NFRB__NFRB IOMUX_PAD(0x27c, 0x084, 0x10, 0, 0, PAD_CTL_PKE) +#define MX25_PAD_NFRB__GPIO_3_31 IOMUX_PAD(0x27c, 0x084, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D15__D15 IOMUX_PAD(0x280, 0x088, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D15__LD16 IOMUX_PAD(0x280, 0x088, 0x01, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D15__GPIO_4_5 IOMUX_PAD(0x280, 0x088, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D14__D14 IOMUX_PAD(0x284, 0x08c, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D14__LD17 IOMUX_PAD(0x284, 0x08c, 0x01, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D14__GPIO_4_6 IOMUX_PAD(0x284, 0x08c, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D13__D13 IOMUX_PAD(0x288, 0x090, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D13__LD18 IOMUX_PAD(0x288, 0x090, 0x01, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D13__GPIO_4_7 IOMUX_PAD(0x288, 0x090, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D12__D12 IOMUX_PAD(0x28c, 0x094, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D12__GPIO_4_8 IOMUX_PAD(0x28c, 0x094, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D11__D11 IOMUX_PAD(0x290, 0x098, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D11__GPIO_4_9 IOMUX_PAD(0x290, 0x098, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D10__D10 IOMUX_PAD(0x294, 0x09c, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D10__GPIO_4_10 IOMUX_PAD(0x294, 0x09c, 0x05, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D10__USBOTG_OC IOMUX_PAD(0x294, 0x09c, 0x06, 0x57c, 0, PAD_CTL_PUS_100K_UP) + +#define MX25_PAD_D9__D9 IOMUX_PAD(0x298, 0x0a0, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D9__GPIO_4_11 IOMUX_PAD(0x298, 0x0a0, 0x05, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D9__USBH2_PWR IOMUX_PAD(0x298, 0x0a0, 0x06, 0, 0, PAD_CTL_PKE) + +#define MX25_PAD_D8__D8 IOMUX_PAD(0x29c, 0x0a4, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D8__GPIO_4_12 IOMUX_PAD(0x29c, 0x0a4, 0x05, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D8__USBH2_OC IOMUX_PAD(0x29c, 0x0a4, 0x06, 0x580, 0, PAD_CTL_PUS_100K_UP) + +#define MX25_PAD_D7__D7 IOMUX_PAD(0x2a0, 0x0a8, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D7__GPIO_4_13 IOMUX_PAD(0x2a0, 0x0a8, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D6__D6 IOMUX_PAD(0x2a4, 0x0ac, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D6__GPIO_4_14 IOMUX_PAD(0x2a4, 0x0ac, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D5__D5 IOMUX_PAD(0x2a8, 0x0b0, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D5__GPIO_4_15 IOMUX_PAD(0x2a8, 0x0b0, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D4__D4 IOMUX_PAD(0x2ac, 0x0b4, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D4__GPIO_4_16 IOMUX_PAD(0x2ac, 0x0b4, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D3__D3 IOMUX_PAD(0x2b0, 0x0b8, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D3__GPIO_4_17 IOMUX_PAD(0x2b0, 0x0b8, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D2__D2 IOMUX_PAD(0x2b4, 0x0bc, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D2__GPIO_4_18 IOMUX_PAD(0x2b4, 0x0bc, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D1__D1 IOMUX_PAD(0x2b8, 0x0c0, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D1__GPIO_4_19 IOMUX_PAD(0x2b8, 0x0c0, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_D0__D0 IOMUX_PAD(0x2bc, 0x0c4, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_D0__GPIO_4_20 IOMUX_PAD(0x2bc, 0x0c4, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD0__LD0 IOMUX_PAD(0x2c0, 0x0c8, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD0__CSI_D0 IOMUX_PAD(0x2c0, 0x0c8, 0x12, 0x488, 0, NO_PAD_CTRL) +#define MX25_PAD_LD0__GPIO_2_15 IOMUX_PAD(0x2c0, 0x0c8, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD1__LD1 IOMUX_PAD(0x2c4, 0x0cc, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD1__CSI_D1 IOMUX_PAD(0x2c4, 0x0cc, 0x12, 0x48c, 0, NO_PAD_CTRL) +#define MX25_PAD_LD1__GPIO_2_16 IOMUX_PAD(0x2c4, 0x0cc, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD2__LD2 IOMUX_PAD(0x2c8, 0x0d0, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD2__GPIO_2_17 IOMUX_PAD(0x2c8, 0x0d0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD3__LD3 IOMUX_PAD(0x2cc, 0x0d4, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD3__GPIO_2_18 IOMUX_PAD(0x2cc, 0x0d4, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD4__LD4 IOMUX_PAD(0x2d0, 0x0d8, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD4__GPIO_2_19 IOMUX_PAD(0x2d0, 0x0d8, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD5__LD5 IOMUX_PAD(0x2d4, 0x0dc, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD5__GPIO_1_19 IOMUX_PAD(0x2d4, 0x0dc, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD6__LD6 IOMUX_PAD(0x2d8, 0x0e0, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD6__GPIO_1_20 IOMUX_PAD(0x2d8, 0x0e0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD7__LD7 IOMUX_PAD(0x2dc, 0x0e4, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD7__GPIO_1_21 IOMUX_PAD(0x2dc, 0x0e4, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LD8__LD8 IOMUX_PAD(0x2e0, 0x0e8, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD8__FEC_TX_ERR IOMUX_PAD(0x2e0, 0x0e8, 0x15, 0, 0, NO_PAD_CTL) + +#define MX25_PAD_LD9__LD9 IOMUX_PAD(0x2e4, 0x0ec, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD9__FEC_COL IOMUX_PAD(0x2e4, 0x0ec, 0x15, 0x504, 1, NO_PAD_CTL) + +#define MX25_PAD_LD10__LD10 IOMUX_PAD(0x2e8, 0x0f0, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD10__FEC_RX_ER IOMUX_PAD(0x2e8, 0x0f0, 0x15, 0x518, 1, NO_PAD_CTL) + +#define MX25_PAD_LD11__LD11 IOMUX_PAD(0x2ec, 0x0f4, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD11__FEC_RDATA2 IOMUX_PAD(0x2ec, 0x0f4, 0x15, 0x50c, 1, NO_PAD_CTL) + +#define MX25_PAD_LD12__LD12 IOMUX_PAD(0x2f0, 0x0f8, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD12__FEC_RDATA3 IOMUX_PAD(0x2f0, 0x0f8, 0x15, 0x510, 1, NO_PAD_CTL) + +#define MX25_PAD_LD13__LD13 IOMUX_PAD(0x2f4, 0x0fc, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD13__FEC_TDATA2 IOMUX_PAD(0x2f4, 0x0fc, 0x15, 0, 0, NO_PAD_CTL) + +#define MX25_PAD_LD14__LD14 IOMUX_PAD(0x2f8, 0x100, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD14__FEC_TDATA3 IOMUX_PAD(0x2f8, 0x100, 0x15, 0, 0, NO_PAD_CTL) + +#define MX25_PAD_LD15__LD15 IOMUX_PAD(0x2fc, 0x104, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LD15__FEC_RX_CLK IOMUX_PAD(0x2fc, 0x104, 0x15, 0x514, 1, NO_PAD_CTL) + +#define MX25_PAD_HSYNC__HSYNC IOMUX_PAD(0x300, 0x108, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_HSYNC__GPIO_1_22 IOMUX_PAD(0x300, 0x108, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_VSYNC__VSYNC IOMUX_PAD(0x304, 0x10c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_VSYNC__GPIO_1_23 IOMUX_PAD(0x304, 0x10c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_LSCLK__LSCLK IOMUX_PAD(0x308, 0x110, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_LSCLK__GPIO_1_24 IOMUX_PAD(0x308, 0x110, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_OE_ACD__OE_ACD IOMUX_PAD(0x30c, 0x114, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_OE_ACD__GPIO_1_25 IOMUX_PAD(0x30c, 0x114, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CONTRAST__CONTRAST IOMUX_PAD(0x310, 0x118, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CONTRAST__FEC_CRS IOMUX_PAD(0x310, 0x118, 0x15, 0x508, 1, NO_PAD_CTL) + +#define MX25_PAD_PWM__PWM IOMUX_PAD(0x314, 0x11c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_PWM__GPIO_1_26 IOMUX_PAD(0x314, 0x11c, 0x15, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_PWM__USBH2_OC IOMUX_PAD(0x314, 0x11c, 0x16, 0x580, 1, PAD_CTL_PUS_100K_UP) + +#define MX25_PAD_CSI_D2__CSI_D2 IOMUX_PAD(0x318, 0x120, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D2__UART5_RXD_MUX IOMUX_PAD(0x318, 0x120, 0x11, 0x578, 1, NO_PAD_CTRL) +#define MX25_PAD_CSI_D2__GPIO_1_27 IOMUX_PAD(0x318, 0x120, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_D3__CSI_D3 IOMUX_PAD(0x31c, 0x124, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D3__GPIO_1_28 IOMUX_PAD(0x31c, 0x124, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_D4__CSI_D4 IOMUX_PAD(0x320, 0x128, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D4__UART5_RTS IOMUX_PAD(0x320, 0x128, 0x11, 0x574, 1, NO_PAD_CTRL) +#define MX25_PAD_CSI_D4__GPIO_1_29 IOMUX_PAD(0x320, 0x128, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_D5__CSI_D5 IOMUX_PAD(0x324, 0x12c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D5__GPIO_1_30 IOMUX_PAD(0x324, 0x12c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_D6__CSI_D6 IOMUX_PAD(0x328, 0x130, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D6__GPIO_1_31 IOMUX_PAD(0x328, 0x130, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_D7__CSI_D7 IOMUX_PAD(0x32c, 0x134, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D7__GPIO_1_6 IOMUX_PAD(0x32c, 0x134, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_D8__CSI_D8 IOMUX_PAD(0x330, 0x138, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D8__GPIO_1_7 IOMUX_PAD(0x330, 0x138, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_D9__CSI_D9 IOMUX_PAD(0x334, 0x13c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_D9__GPIO_4_21 IOMUX_PAD(0x334, 0x13c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_MCLK__CSI_MCLK IOMUX_PAD(0x338, 0x140, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_MCLK__GPIO_1_8 IOMUX_PAD(0x338, 0x140, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_VSYNC__CSI_VSYNC IOMUX_PAD(0x33c, 0x144, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_VSYNC__GPIO_1_9 IOMUX_PAD(0x33c, 0x144, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_HSYNC__CSI_HSYNC IOMUX_PAD(0x340, 0x148, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_HSYNC__GPIO_1_10 IOMUX_PAD(0x340, 0x148, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK IOMUX_PAD(0x344, 0x14c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSI_PIXCLK__GPIO_1_11 IOMUX_PAD(0x344, 0x14c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_I2C1_CLK__I2C1_CLK IOMUX_PAD(0x348, 0x150, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_I2C1_CLK__GPIO_1_12 IOMUX_PAD(0x348, 0x150, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_I2C1_DAT__I2C1_DAT IOMUX_PAD(0x34c, 0x154, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_I2C1_DAT__GPIO_1_13 IOMUX_PAD(0x34c, 0x154, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI IOMUX_PAD(0x350, 0x158, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSPI1_MOSI__GPIO_1_14 IOMUX_PAD(0x350, 0x158, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSPI1_MISO__CSPI1_MISO IOMUX_PAD(0x354, 0x15c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSPI1_MISO__GPIO_1_15 IOMUX_PAD(0x354, 0x15c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSPI1_SS0__CSPI1_SS0 IOMUX_PAD(0x358, 0x160, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSPI1_SS0__GPIO_1_16 IOMUX_PAD(0x358, 0x160, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSPI1_SS1__CSPI1_SS1 IOMUX_PAD(0x35c, 0x164, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSPI1_SS1__GPIO_1_17 IOMUX_PAD(0x35c, 0x164, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK IOMUX_PAD(0x360, 0x168, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CSPI1_SCLK__GPIO_1_18 IOMUX_PAD(0x360, 0x168, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CSPI1_RDY__CSPI1_RDY IOMUX_PAD(0x364, 0x16c, 0x10, 0, 0, PAD_CTL_PKE) +#define MX25_PAD_CSPI1_RDY__GPIO_2_22 IOMUX_PAD(0x364, 0x16c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART1_RXD__UART1_RXD IOMUX_PAD(0x368, 0x170, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN) +#define MX25_PAD_UART1_RXD__GPIO_4_22 IOMUX_PAD(0x368, 0x170, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART1_TXD__UART1_TXD IOMUX_PAD(0x36c, 0x174, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_UART1_TXD__GPIO_4_23 IOMUX_PAD(0x36c, 0x174, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART1_RTS__UART1_RTS IOMUX_PAD(0x370, 0x178, 0x10, 0, 0, PAD_CTL_PUS_100K_UP) +#define MX25_PAD_UART1_RTS__CSI_D0 IOMUX_PAD(0x370, 0x178, 0x11, 0x488, 1, NO_PAD_CTRL) +#define MX25_PAD_UART1_RTS__GPIO_4_24 IOMUX_PAD(0x370, 0x178, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART1_CTS__UART1_CTS IOMUX_PAD(0x374, 0x17c, 0x10, 0, 0, PAD_CTL_PUS_100K_UP) +#define MX25_PAD_UART1_CTS__CSI_D1 IOMUX_PAD(0x374, 0x17c, 0x11, 0x48c, 1, NO_PAD_CTRL) +#define MX25_PAD_UART1_CTS__GPIO_4_25 IOMUX_PAD(0x374, 0x17c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART2_RXD__UART2_RXD IOMUX_PAD(0x378, 0x180, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_UART2_RXD__GPIO_4_26 IOMUX_PAD(0x378, 0x180, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART2_TXD__UART2_TXD IOMUX_PAD(0x37c, 0x184, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_UART2_TXD__GPIO_4_27 IOMUX_PAD(0x37c, 0x184, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART2_RTS__UART2_RTS IOMUX_PAD(0x380, 0x188, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_UART2_RTS__FEC_COL IOMUX_PAD(0x380, 0x188, 0x12, 0x504, 2, NO_PAD_CTL) +#define MX25_PAD_UART2_RTS__GPIO_4_28 IOMUX_PAD(0x380, 0x188, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UART2_CTS__FEC_RX_ER IOMUX_PAD(0x384, 0x18c, 0x12, 0x518, 2, NO_PAD_CTL) +#define MX25_PAD_UART2_CTS__UART2_CTS IOMUX_PAD(0x384, 0x18c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_UART2_CTS__GPIO_4_29 IOMUX_PAD(0x384, 0x18c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_SD1_CMD__SD1_CMD IOMUX_PAD(0x388, 0x190, 0x10, 0, 0, PAD_CTL_PUS_47K_UP) +#define MX25_PAD_SD1_CMD__FEC_RDATA2 IOMUX_PAD(0x388, 0x190, 0x12, 0x50c, 2, NO_PAD_CTL) +#define MX25_PAD_SD1_CMD__GPIO_2_23 IOMUX_PAD(0x388, 0x190, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_SD1_CLK__SD1_CLK IOMUX_PAD(0x38c, 0x194, 0x10, 0, 0, PAD_CTL_PUS_47K_UP) +#define MX25_PAD_SD1_CLK__FEC_RDATA3 IOMUX_PAD(0x38c, 0x194, 0x12, 0x510, 2, NO_PAD_CTL) +#define MX25_PAD_SD1_CLK__GPIO_2_24 IOMUX_PAD(0x38c, 0x194, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_SD1_DATA0__SD1_DATA0 IOMUX_PAD(0x390, 0x198, 0x10, 0, 0, PAD_CTL_PUS_47K_UP) +#define MX25_PAD_SD1_DATA0__GPIO_2_25 IOMUX_PAD(0x390, 0x198, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_SD1_DATA1__SD1_DATA1 IOMUX_PAD(0x394, 0x19c, 0x10, 0, 0, PAD_CTL_PUS_47K_UP) +#define MX25_PAD_SD1_DATA1__AUD7_RXD IOMUX_PAD(0x394, 0x19c, 0x13, 0x478, 0, NO_PAD_CTRL) +#define MX25_PAD_SD1_DATA1__GPIO_2_26 IOMUX_PAD(0x394, 0x19c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_SD1_DATA2__SD1_DATA2 IOMUX_PAD(0x398, 0x1a0, 0x10, 0, 0, PAD_CTL_PUS_47K_UP) +#define MX25_PAD_SD1_DATA2__FEC_RX_CLK IOMUX_PAD(0x398, 0x1a0, 0x15, 0x514, 2, NO_PAD_CTL) +#define MX25_PAD_SD1_DATA2__GPIO_2_27 IOMUX_PAD(0x398, 0x1a0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_SD1_DATA3__SD1_DATA3 IOMUX_PAD(0x39c, 0x1a4, 0x10, 0, 0, PAD_CTL_PUS_47K_UP) +#define MX25_PAD_SD1_DATA3__FEC_CRS IOMUX_PAD(0x39c, 0x1a4, 0x10, 0x508, 2, NO_PAD_CTL) +#define MX25_PAD_SD1_DATA3__GPIO_2_28 IOMUX_PAD(0x39c, 0x1a4, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_ROW0__KPP_ROW0 IOMUX_PAD(0x3a0, 0x1a8, 0x10, 0, 0, PAD_CTL_PKE) +#define MX25_PAD_KPP_ROW0__GPIO_2_29 IOMUX_PAD(0x3a0, 0x1a8, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_ROW1__KPP_ROW1 IOMUX_PAD(0x3a4, 0x1ac, 0x10, 0, 0, PAD_CTL_PKE) +#define MX25_PAD_KPP_ROW1__GPIO_2_30 IOMUX_PAD(0x3a4, 0x1ac, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_ROW2__KPP_ROW2 IOMUX_PAD(0x3a8, 0x1b0, 0x10, 0, 0, PAD_CTL_PKE) +#define MX25_PAD_KPP_ROW2__CSI_D0 IOMUX_PAD(0x3a8, 0x1b0, 0x13, 0x488, 2, NO_PAD_CTRL) +#define MX25_PAD_KPP_ROW2__GPIO_2_31 IOMUX_PAD(0x3a8, 0x1b0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_ROW3__KPP_ROW3 IOMUX_PAD(0x3ac, 0x1b4, 0x10, 0, 0, PAD_CTL_PKE) +#define MX25_PAD_KPP_ROW3__CSI_LD1 IOMUX_PAD(0x3ac, 0x1b4, 0x13, 0x48c, 2, NO_PAD_CTRL) +#define MX25_PAD_KPP_ROW3__GPIO_3_0 IOMUX_PAD(0x3ac, 0x1b4, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_COL0__KPP_COL0 IOMUX_PAD(0x3b0, 0x1b8, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE) +#define MX25_PAD_KPP_COL0__GPIO_3_1 IOMUX_PAD(0x3b0, 0x1b8, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_COL1__KPP_COL1 IOMUX_PAD(0x3b4, 0x1bc, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE) +#define MX25_PAD_KPP_COL1__GPIO_3_2 IOMUX_PAD(0x3b4, 0x1bc, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_COL2__KPP_COL2 IOMUX_PAD(0x3b8, 0x1c0, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE) +#define MX25_PAD_KPP_COL2__GPIO_3_3 IOMUX_PAD(0x3b8, 0x1c0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_KPP_COL3__KPP_COL3 IOMUX_PAD(0x3bc, 0x1c4, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE) +#define MX25_PAD_KPP_COL3__GPIO_3_4 IOMUX_PAD(0x3bc, 0x1c4, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_MDC__FEC_MDC IOMUX_PAD(0x3c0, 0x1c8, 0x10, 0, 0, NO_PAD_CTL) +#define MX25_PAD_FEC_MDC__AUD4_TXD IOMUX_PAD(0x3c0, 0x1c8, 0x12, 0x464, 1, NO_PAD_CTRL) +#define MX25_PAD_FEC_MDC__GPIO_3_5 IOMUX_PAD(0x3c0, 0x1c8, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_MDIO__FEC_MDIO IOMUX_PAD(0x3c4, 0x1cc, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_22K_UP) +#define MX25_PAD_FEC_MDIO__AUD4_RXD IOMUX_PAD(0x3c4, 0x1cc, 0x12, 0x460, 1, NO_PAD_CTRL) +#define MX25_PAD_FEC_MDIO__GPIO_3_6 IOMUX_PAD(0x3c4, 0x1cc, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_TDATA0__FEC_TDATA0 IOMUX_PAD(0x3c8, 0x1d0, 0x10, 0, 0, NO_PAD_CTL) +#define MX25_PAD_FEC_TDATA0__GPIO_3_7 IOMUX_PAD(0x3c8, 0x1d0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_TDATA1__FEC_TDATA1 IOMUX_PAD(0x3cc, 0x1d4, 0x10, 0, 0, NO_PAD_CTL) +#define MX25_PAD_FEC_TDATA1__AUD4_TXFS IOMUX_PAD(0x3cc, 0x1d4, 0x12, 0x474, 1, NO_PAD_CTRL) +#define MX25_PAD_FEC_TDATA1__GPIO_3_8 IOMUX_PAD(0x3cc, 0x1d4, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_TX_EN__FEC_TX_EN IOMUX_PAD(0x3d0, 0x1d8, 0x10, 0, 0, NO_PAD_CTL) +#define MX25_PAD_FEC_TX_EN__GPIO_3_9 IOMUX_PAD(0x3d0, 0x1d8, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_RDATA0__FEC_RDATA0 IOMUX_PAD(0x3d4, 0x1dc, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTL) +#define MX25_PAD_FEC_RDATA0__GPIO_3_10 IOMUX_PAD(0x3d4, 0x1dc, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_RDATA1__FEC_RDATA1 IOMUX_PAD(0x3d8, 0x1e0, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTL) +#define MX25_PAD_FEC_RDATA1__GPIO_3_11 IOMUX_PAD(0x3d8, 0x1e0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_RX_DV__FEC_RX_DV IOMUX_PAD(0x3dc, 0x1e4, 0x10, 0, 0, PAD_CTL_PUS_100K_DOWN | NO_PAD_CTL) +#define MX25_PAD_FEC_RX_DV__CAN2_RX IOMUX_PAD(0x3dc, 0x1e4, 0x14, 0x484, 0, PAD_CTL_PUS_22K_UP) +#define MX25_PAD_FEC_RX_DV__GPIO_3_12 IOMUX_PAD(0x3dc, 0x1e4, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_FEC_TX_CLK__FEC_TX_CLK IOMUX_PAD(0x3e0, 0x1e8, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_100K_DOWN) +#define MX25_PAD_FEC_TX_CLK__GPIO_3_13 IOMUX_PAD(0x3e0, 0x1e8, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_RTCK__RTCK IOMUX_PAD(0x3e4, 0x1ec, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_RTCK__OWIRE IOMUX_PAD(0x3e4, 0x1ec, 0x11, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_RTCK__GPIO_3_14 IOMUX_PAD(0x3e4, 0x1ec, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_DE_B__DE_B IOMUX_PAD(0x3ec, 0x1f0, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_DE_B__GPIO_2_20 IOMUX_PAD(0x3ec, 0x1f0, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_TDO__TDO IOMUX_PAD(0x3e8, 0x000, 0x00, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_GPIO_A__GPIO_A IOMUX_PAD(0x3f0, 0x1f4, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_A__CAN1_TX IOMUX_PAD(0x3f0, 0x1f4, 0x16, 0, 0, PAD_CTL_PUS_22K_UP) +#define MX25_PAD_GPIO_A__USBOTG_PWR IOMUX_PAD(0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PKE) + +#define MX25_PAD_GPIO_B__GPIO_B IOMUX_PAD(0x3f4, 0x1f8, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_B__CAN1_RX IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K) +#define MX25_PAD_GPIO_B__USBOTG_OC IOMUX_PAD(0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PUS_100K_UP) + +#define MX25_PAD_GPIO_C__GPIO_C IOMUX_PAD(0x3f8, 0x1fc, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_C__CAN2_TX IOMUX_PAD(0x3f8, 0x1fc, 0x16, 0, 0, PAD_CTL_PUS_22K_UP) + +#define MX25_PAD_GPIO_D__GPIO_D IOMUX_PAD(0x3fc, 0x200, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_D__CAN2_RX IOMUX_PAD(0x3fc, 0x200, 0x16, 0x484, 1, PAD_CTL_PUS_22K_UP) + +#define MX25_PAD_GPIO_E__GPIO_E IOMUX_PAD(0x400, 0x204, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_E__AUD7_TXD IOMUX_PAD(0x400, 0x204, 0x14, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_GPIO_F__GPIO_F IOMUX_PAD(0x404, 0x208, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_GPIO_F__AUD7_TXC IOMUX_PAD(0x404, 0x208, 0x14, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK IOMUX_PAD(0x000, 0x20c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_EXT_ARMCLK__GPIO_3_15 IOMUX_PAD(0x000, 0x20c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK IOMUX_PAD(0x000, 0x210, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_UPLL_BYPCLK__GPIO_3_16 IOMUX_PAD(0x000, 0x210, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_VSTBY_REQ__VSTBY_REQ IOMUX_PAD(0x408, 0x214, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_VSTBY_REQ__AUD7_TXFS IOMUX_PAD(0x408, 0x214, 0x14, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_VSTBY_REQ__GPIO_3_17 IOMUX_PAD(0x408, 0x214, 0x15, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_VSTBY_ACK__VSTBY_ACK IOMUX_PAD(0x40c, 0x218, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_VSTBY_ACK__GPIO_3_18 IOMUX_PAD(0x40c, 0x218, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_POWER_FAIL__POWER_FAIL IOMUX_PAD(0x410, 0x21c, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_POWER_FAIL__AUD7_RXD IOMUX_PAD(0x410, 0x21c, 0x14, 0x478, 1, NO_PAD_CTRL) +#define MX25_PAD_POWER_FAIL__GPIO_3_19 IOMUX_PAD(0x410, 0x21c, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CLKO__CLKO IOMUX_PAD(0x414, 0x220, 0x10, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CLKO__GPIO_2_21 IOMUX_PAD(0x414, 0x220, 0x15, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_BOOT_MODE0__BOOT_MODE0 IOMUX_PAD(0x000, 0x224, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_BOOT_MODE0__GPIO_4_30 IOMUX_PAD(0x000, 0x224, 0x05, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_BOOT_MODE1__BOOT_MODE1 IOMUX_PAD(0x000, 0x228, 0x00, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_BOOT_MODE1__GPIO_4_31 IOMUX_PAD(0x000, 0x228, 0x05, 0, 0, NO_PAD_CTRL) + +#define MX25_PAD_CTL_GRP_DVS_MISC IOMUX_PAD(0x418, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_FEC IOMUX_PAD(0x41c, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DVS_JTAG IOMUX_PAD(0x420, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_NFC IOMUX_PAD(0x424, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_CSI IOMUX_PAD(0x428, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_WEIM IOMUX_PAD(0x42c, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_DDR IOMUX_PAD(0x430, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DVS_CRM IOMUX_PAD(0x434, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_KPP IOMUX_PAD(0x438, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_SDHC1 IOMUX_PAD(0x43c, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_LCD IOMUX_PAD(0x440, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_UART IOMUX_PAD(0x444, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DVS_NFC IOMUX_PAD(0x448, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DVS_CSI IOMUX_PAD(0x44c, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DSE_CSPI1 IOMUX_PAD(0x450, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DDRTYPE IOMUX_PAD(0x454, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DVS_SDHC1 IOMUX_PAD(0x458, 0x000, 0, 0, 0, NO_PAD_CTRL) +#define MX25_PAD_CTL_GRP_DVS_LCD IOMUX_PAD(0x45c, 0x000, 0, 0, 0, NO_PAD_CTRL) + +#endif // __ASSEMBLY__ +#endif // __IOMUX_MX25_H__ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h index 27f8d1b2bc6b..446f86763816 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h @@ -602,6 +602,8 @@ enum iomux_pins { #define MX31_PIN_I2C_DAT__SDA IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC) #define MX31_PIN_DCD_DTE1__I2C2_SDA IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2) #define MX31_PIN_RI_DTE1__I2C2_SCL IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2) +#define MX31_PIN_CSPI2_SS2__I2C3_SDA IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_ALT1) +#define MX31_PIN_CSPI2_SCLK__I2C3_SCL IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_ALT1) #define MX31_PIN_CSI_D4__CSI_D4 IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSI_D5__CSI_D5 IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC) #define MX31_PIN_CSI_D6__CSI_D6 IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC) @@ -633,6 +635,19 @@ enum iomux_pins { #define MX31_PIN_USBOTG_DIR__USBOTG_DIR IOMUX_MODE(MX31_PIN_USBOTG_DIR, IOMUX_CONFIG_FUNC) #define MX31_PIN_USBOTG_NXT__USBOTG_NXT IOMUX_MODE(MX31_PIN_USBOTG_NXT, IOMUX_CONFIG_FUNC) #define MX31_PIN_USBOTG_STP__USBOTG_STP IOMUX_MODE(MX31_PIN_USBOTG_STP, IOMUX_CONFIG_FUNC) +#define MX31_PIN_CSPI1_MOSI__USBH1_RXDM IOMUX_MODE(MX31_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT1) +#define MX31_PIN_CSPI1_MISO__USBH1_RXDP IOMUX_MODE(MX31_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT1) +#define MX31_PIN_CSPI1_SS0__USBH1_TXDM IOMUX_MODE(MX31_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT1) +#define MX31_PIN_CSPI1_SS1__USBH1_TXDP IOMUX_MODE(MX31_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT1) +#define MX31_PIN_CSPI1_SS2__USBH1_RCV IOMUX_MODE(MX31_PIN_CSPI1_SS2, IOMUX_CONFIG_ALT1) +#define MX31_PIN_CSPI1_SCLK__USBH1_OEB IOMUX_MODE(MX31_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT1) +#define MX31_PIN_CSPI1_SPI_RDY__USBH1_FS IOMUX_MODE(MX31_PIN_CSPI1_SPI_RDY, IOMUX_CONFIG_ALT1) +#define MX31_PIN_USBH2_DATA0__USBH2_DATA0 IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC) +#define MX31_PIN_USBH2_DATA1__USBH2_DATA1 IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC) +#define MX31_PIN_USBH2_CLK__USBH2_CLK IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC) +#define MX31_PIN_USBH2_DIR__USBH2_DIR IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC) +#define MX31_PIN_USBH2_NXT__USBH2_NXT IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC) +#define MX31_PIN_USBH2_STP__USBH2_STP IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC) #define MX31_PIN_USB_OC__GPIO1_30 IOMUX_MODE(MX31_PIN_USB_OC, IOMUX_CONFIG_GPIO) #define MX31_PIN_I2C_DAT__I2C1_SDA IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC) #define MX31_PIN_I2C_CLK__I2C1_SCL IOMUX_MODE(MX31_PIN_I2C_CLK, IOMUX_CONFIG_FUNC) @@ -667,6 +682,18 @@ enum iomux_pins { #define MX31_PIN_GPIO3_0__GPIO3_0 IOMUX_MODE(MX31_PIN_GPIO3_0, IOMUX_CONFIG_GPIO) #define MX31_PIN_GPIO3_1__GPIO3_1 IOMUX_MODE(MX31_PIN_GPIO3_1, IOMUX_CONFIG_GPIO) #define MX31_PIN_TXD2__GPIO1_28 IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_GPIO) +#define MX31_PIN_GPIO1_0__GPIO1_0 IOMUX_MODE(MX31_PIN_GPIO1_0, IOMUX_CONFIG_GPIO) +#define MX31_PIN_SVEN0__GPIO2_0 IOMUX_MODE(MX31_PIN_SVEN0, IOMUX_CONFIG_GPIO) +#define MX31_PIN_STX0__GPIO2_1 IOMUX_MODE(MX31_PIN_STX0, IOMUX_CONFIG_GPIO) +#define MX31_PIN_SRX0__GPIO2_2 IOMUX_MODE(MX31_PIN_SRX0, IOMUX_CONFIG_GPIO) +#define MX31_PIN_SIMPD0__GPIO2_3 IOMUX_MODE(MX31_PIN_SIMPD0, IOMUX_CONFIG_GPIO) +#define MX31_PIN_DTR_DCE1__GPIO2_8 IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_GPIO) +#define MX31_PIN_DSR_DCE1__GPIO2_9 IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_GPIO) +#define MX31_PIN_RI_DCE1__GPIO2_10 IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_GPIO) +#define MX31_PIN_DCD_DCE1__GPIO2_11 IOMUX_MODE(MX31_PIN_DCD_DCE1, IOMUX_CONFIG_GPIO) +#define MX31_PIN_STXD5__GPIO1_21 IOMUX_MODE(MX31_PIN_STXD5, IOMUX_CONFIG_GPIO) +#define MX31_PIN_SRXD5__GPIO1_22 IOMUX_MODE(MX31_PIN_SRXD5, IOMUX_CONFIG_GPIO) + /*XXX: The SS0, SS1, SS2, SS3 lines of spi3 are multiplexed by cspi2_ss0, cspi2_ss1, cspi1_ss0 * cspi1_ss1*/ diff --git a/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h b/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h new file mode 100644 index 000000000000..9f13061192c8 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h @@ -0,0 +1,287 @@ +/* + * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> + * Copyright (C) 2009 by Dmitriy Taychenachev <dimichxp@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __MACH_IOMUX_MXC91231_H__ +#define __MACH_IOMUX_MXC91231_H__ + +/* + * various IOMUX output functions + */ + +#define IOMUX_OCONFIG_GPIO (0 << 4) /* used as GPIO */ +#define IOMUX_OCONFIG_FUNC (1 << 4) /* used as function */ +#define IOMUX_OCONFIG_ALT1 (2 << 4) /* used as alternate function 1 */ +#define IOMUX_OCONFIG_ALT2 (3 << 4) /* used as alternate function 2 */ +#define IOMUX_OCONFIG_ALT3 (4 << 4) /* used as alternate function 3 */ +#define IOMUX_OCONFIG_ALT4 (5 << 4) /* used as alternate function 4 */ +#define IOMUX_OCONFIG_ALT5 (6 << 4) /* used as alternate function 5 */ +#define IOMUX_OCONFIG_ALT6 (7 << 4) /* used as alternate function 6 */ +#define IOMUX_ICONFIG_NONE 0 /* not configured for input */ +#define IOMUX_ICONFIG_GPIO 1 /* used as GPIO */ +#define IOMUX_ICONFIG_FUNC 2 /* used as function */ +#define IOMUX_ICONFIG_ALT1 4 /* used as alternate function 1 */ +#define IOMUX_ICONFIG_ALT2 8 /* used as alternate function 2 */ + +#define IOMUX_CONFIG_GPIO (IOMUX_OCONFIG_GPIO | IOMUX_ICONFIG_GPIO) +#define IOMUX_CONFIG_FUNC (IOMUX_OCONFIG_FUNC | IOMUX_ICONFIG_FUNC) +#define IOMUX_CONFIG_ALT1 (IOMUX_OCONFIG_ALT1 | IOMUX_ICONFIG_ALT1) +#define IOMUX_CONFIG_ALT2 (IOMUX_OCONFIG_ALT2 | IOMUX_ICONFIG_ALT2) + +/* + * setups a single pin: + * - reserves the pin so that it is not claimed by another driver + * - setups the iomux according to the configuration + * - if the pin is configured as a GPIO, we claim it throug kernel gpiolib + */ +int mxc_iomux_alloc_pin(const unsigned int pin_mode, const char *label); +/* + * setups mutliple pins + * convenient way to call the above function with tables + */ +int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count, + const char *label); + +/* + * releases a single pin: + * - make it available for a future use by another driver + * - frees the GPIO if the pin was configured as GPIO + * - DOES NOT reconfigure the IOMUX in its reset state + */ +void mxc_iomux_release_pin(const unsigned int pin_mode); +/* + * releases multiple pins + * convenvient way to call the above function with tables + */ +void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count); + +#define MUX_SIDE_AP (0) +#define MUX_SIDE_SP (1) + +#define MUX_SIDE_SHIFT (26) +#define MUX_SIDE_MASK (0x1 << MUX_SIDE_SHIFT) + +#define MUX_GPIO_PORT_SHIFT (23) +#define MUX_GPIO_PORT_MASK (0x7 << MUX_GPIO_PORT_SHIFT) + +#define MUX_GPIO_PIN_SHIFT (20) +#define MUX_GPIO_PIN_MASK (0x1f << MUX_GPIO_PIN_SHIFT) + +#define MUX_REG_SHIFT (15) +#define MUX_REG_MASK (0x1f << MUX_REG_SHIFT) + +#define MUX_FIELD_SHIFT (13) +#define MUX_FIELD_MASK (0x3 << MUX_FIELD_SHIFT) + +#define MUX_PADGRP_SHIFT (8) +#define MUX_PADGRP_MASK (0x1f << MUX_PADGRP_SHIFT) + +#define MUX_PIN_MASK (0xffffff << 8) + +#define GPIO_PORT_MAX (3) + +#define IOMUX_PIN(side, gport, gpin, ctlreg, ctlfield, padgrp) \ + (((side) << MUX_SIDE_SHIFT) | \ + (gport << MUX_GPIO_PORT_SHIFT) | \ + ((gpin) << MUX_GPIO_PIN_SHIFT) | \ + ((ctlreg) << MUX_REG_SHIFT) | \ + ((ctlfield) << MUX_FIELD_SHIFT) | \ + ((padgrp) << MUX_PADGRP_SHIFT)) + +#define MUX_MODE_OUT_SHIFT (4) +#define MUX_MODE_IN_SHIFT (0) +#define MUX_MODE_SHIFT (0) +#define MUX_MODE_MASK (0xff << MUX_MODE_SHIFT) + +#define IOMUX_MODE(pin, mode) \ + (pin | (mode << MUX_MODE_SHIFT)) + +enum iomux_pins { + /* AP Side pins */ + MXC91231_PIN_AP_CLE = IOMUX_PIN(0, 0, 0, 0, 0, 24), + MXC91231_PIN_AP_ALE = IOMUX_PIN(0, 0, 1, 0, 1, 24), + MXC91231_PIN_AP_CE_B = IOMUX_PIN(0, 0, 2, 0, 2, 24), + MXC91231_PIN_AP_RE_B = IOMUX_PIN(0, 0, 3, 0, 3, 24), + MXC91231_PIN_AP_WE_B = IOMUX_PIN(0, 0, 4, 1, 0, 24), + MXC91231_PIN_AP_WP_B = IOMUX_PIN(0, 0, 5, 1, 1, 24), + MXC91231_PIN_AP_BSY_B = IOMUX_PIN(0, 0, 6, 1, 2, 24), + MXC91231_PIN_AP_U1_TXD = IOMUX_PIN(0, 0, 7, 1, 3, 28), + MXC91231_PIN_AP_U1_RXD = IOMUX_PIN(0, 0, 8, 2, 0, 28), + MXC91231_PIN_AP_U1_RTS_B = IOMUX_PIN(0, 0, 9, 2, 1, 28), + MXC91231_PIN_AP_U1_CTS_B = IOMUX_PIN(0, 0, 10, 2, 2, 28), + MXC91231_PIN_AP_AD1_TXD = IOMUX_PIN(0, 0, 11, 2, 3, 9), + MXC91231_PIN_AP_AD1_RXD = IOMUX_PIN(0, 0, 12, 3, 0, 9), + MXC91231_PIN_AP_AD1_TXC = IOMUX_PIN(0, 0, 13, 3, 1, 9), + MXC91231_PIN_AP_AD1_TXFS = IOMUX_PIN(0, 0, 14, 3, 2, 9), + MXC91231_PIN_AP_AD2_TXD = IOMUX_PIN(0, 0, 15, 3, 3, 9), + MXC91231_PIN_AP_AD2_RXD = IOMUX_PIN(0, 0, 16, 4, 0, 9), + MXC91231_PIN_AP_AD2_TXC = IOMUX_PIN(0, 0, 17, 4, 1, 9), + MXC91231_PIN_AP_AD2_TXFS = IOMUX_PIN(0, 0, 18, 4, 2, 9), + MXC91231_PIN_AP_OWDAT = IOMUX_PIN(0, 0, 19, 4, 3, 28), + MXC91231_PIN_AP_IPU_LD17 = IOMUX_PIN(0, 0, 20, 5, 0, 28), + MXC91231_PIN_AP_IPU_D3_VSYNC = IOMUX_PIN(0, 0, 21, 5, 1, 28), + MXC91231_PIN_AP_IPU_D3_HSYNC = IOMUX_PIN(0, 0, 22, 5, 2, 28), + MXC91231_PIN_AP_IPU_D3_CLK = IOMUX_PIN(0, 0, 23, 5, 3, 28), + MXC91231_PIN_AP_IPU_D3_DRDY = IOMUX_PIN(0, 0, 24, 6, 0, 28), + MXC91231_PIN_AP_IPU_D3_CONTR = IOMUX_PIN(0, 0, 25, 6, 1, 28), + MXC91231_PIN_AP_IPU_D0_CS = IOMUX_PIN(0, 0, 26, 6, 2, 28), + MXC91231_PIN_AP_IPU_LD16 = IOMUX_PIN(0, 0, 27, 6, 3, 28), + MXC91231_PIN_AP_IPU_D2_CS = IOMUX_PIN(0, 0, 28, 7, 0, 28), + MXC91231_PIN_AP_IPU_PAR_RS = IOMUX_PIN(0, 0, 29, 7, 1, 28), + MXC91231_PIN_AP_IPU_D3_PS = IOMUX_PIN(0, 0, 30, 7, 2, 28), + MXC91231_PIN_AP_IPU_D3_CLS = IOMUX_PIN(0, 0, 31, 7, 3, 28), + MXC91231_PIN_AP_IPU_RD = IOMUX_PIN(0, 1, 0, 8, 0, 28), + MXC91231_PIN_AP_IPU_WR = IOMUX_PIN(0, 1, 1, 8, 1, 28), + MXC91231_PIN_AP_IPU_LD0 = IOMUX_PIN(0, 7, 0, 8, 2, 28), + MXC91231_PIN_AP_IPU_LD1 = IOMUX_PIN(0, 7, 0, 8, 3, 28), + MXC91231_PIN_AP_IPU_LD2 = IOMUX_PIN(0, 7, 0, 9, 0, 28), + MXC91231_PIN_AP_IPU_LD3 = IOMUX_PIN(0, 1, 2, 9, 1, 28), + MXC91231_PIN_AP_IPU_LD4 = IOMUX_PIN(0, 1, 3, 9, 2, 28), + MXC91231_PIN_AP_IPU_LD5 = IOMUX_PIN(0, 1, 4, 9, 3, 28), + MXC91231_PIN_AP_IPU_LD6 = IOMUX_PIN(0, 1, 5, 10, 0, 28), + MXC91231_PIN_AP_IPU_LD7 = IOMUX_PIN(0, 1, 6, 10, 1, 28), + MXC91231_PIN_AP_IPU_LD8 = IOMUX_PIN(0, 1, 7, 10, 2, 28), + MXC91231_PIN_AP_IPU_LD9 = IOMUX_PIN(0, 1, 8, 10, 3, 28), + MXC91231_PIN_AP_IPU_LD10 = IOMUX_PIN(0, 1, 9, 11, 0, 28), + MXC91231_PIN_AP_IPU_LD11 = IOMUX_PIN(0, 1, 10, 11, 1, 28), + MXC91231_PIN_AP_IPU_LD12 = IOMUX_PIN(0, 1, 11, 11, 2, 28), + MXC91231_PIN_AP_IPU_LD13 = IOMUX_PIN(0, 1, 12, 11, 3, 28), + MXC91231_PIN_AP_IPU_LD14 = IOMUX_PIN(0, 1, 13, 12, 0, 28), + MXC91231_PIN_AP_IPU_LD15 = IOMUX_PIN(0, 1, 14, 12, 1, 28), + MXC91231_PIN_AP_KPROW4 = IOMUX_PIN(0, 7, 0, 12, 2, 10), + MXC91231_PIN_AP_KPROW5 = IOMUX_PIN(0, 1, 16, 12, 3, 10), + MXC91231_PIN_AP_GPIO_AP_B17 = IOMUX_PIN(0, 1, 17, 13, 0, 10), + MXC91231_PIN_AP_GPIO_AP_B18 = IOMUX_PIN(0, 1, 18, 13, 1, 10), + MXC91231_PIN_AP_KPCOL3 = IOMUX_PIN(0, 1, 19, 13, 2, 11), + MXC91231_PIN_AP_KPCOL4 = IOMUX_PIN(0, 1, 20, 13, 3, 11), + MXC91231_PIN_AP_KPCOL5 = IOMUX_PIN(0, 1, 21, 14, 0, 11), + MXC91231_PIN_AP_GPIO_AP_B22 = IOMUX_PIN(0, 1, 22, 14, 1, 11), + MXC91231_PIN_AP_GPIO_AP_B23 = IOMUX_PIN(0, 1, 23, 14, 2, 11), + MXC91231_PIN_AP_CSI_D0 = IOMUX_PIN(0, 1, 24, 14, 3, 21), + MXC91231_PIN_AP_CSI_D1 = IOMUX_PIN(0, 1, 25, 15, 0, 21), + MXC91231_PIN_AP_CSI_D2 = IOMUX_PIN(0, 1, 26, 15, 1, 21), + MXC91231_PIN_AP_CSI_D3 = IOMUX_PIN(0, 1, 27, 15, 2, 21), + MXC91231_PIN_AP_CSI_D4 = IOMUX_PIN(0, 1, 28, 15, 3, 21), + MXC91231_PIN_AP_CSI_D5 = IOMUX_PIN(0, 1, 29, 16, 0, 21), + MXC91231_PIN_AP_CSI_D6 = IOMUX_PIN(0, 1, 30, 16, 1, 21), + MXC91231_PIN_AP_CSI_D7 = IOMUX_PIN(0, 1, 31, 16, 2, 21), + MXC91231_PIN_AP_CSI_D8 = IOMUX_PIN(0, 2, 0, 16, 3, 21), + MXC91231_PIN_AP_CSI_D9 = IOMUX_PIN(0, 2, 1, 17, 0, 21), + MXC91231_PIN_AP_CSI_MCLK = IOMUX_PIN(0, 2, 2, 17, 1, 21), + MXC91231_PIN_AP_CSI_VSYNC = IOMUX_PIN(0, 2, 3, 17, 2, 21), + MXC91231_PIN_AP_CSI_HSYNC = IOMUX_PIN(0, 2, 4, 17, 3, 21), + MXC91231_PIN_AP_CSI_PIXCLK = IOMUX_PIN(0, 2, 5, 18, 0, 21), + MXC91231_PIN_AP_I2CLK = IOMUX_PIN(0, 2, 6, 18, 1, 12), + MXC91231_PIN_AP_I2DAT = IOMUX_PIN(0, 2, 7, 18, 2, 12), + MXC91231_PIN_AP_GPIO_AP_C8 = IOMUX_PIN(0, 2, 8, 18, 3, 9), + MXC91231_PIN_AP_GPIO_AP_C9 = IOMUX_PIN(0, 2, 9, 19, 0, 9), + MXC91231_PIN_AP_GPIO_AP_C10 = IOMUX_PIN(0, 2, 10, 19, 1, 9), + MXC91231_PIN_AP_GPIO_AP_C11 = IOMUX_PIN(0, 2, 11, 19, 2, 9), + MXC91231_PIN_AP_GPIO_AP_C12 = IOMUX_PIN(0, 2, 12, 19, 3, 9), + MXC91231_PIN_AP_GPIO_AP_C13 = IOMUX_PIN(0, 2, 13, 20, 0, 28), + MXC91231_PIN_AP_GPIO_AP_C14 = IOMUX_PIN(0, 2, 14, 20, 1, 28), + MXC91231_PIN_AP_GPIO_AP_C15 = IOMUX_PIN(0, 2, 15, 20, 2, 9), + MXC91231_PIN_AP_GPIO_AP_C16 = IOMUX_PIN(0, 2, 16, 20, 3, 9), + MXC91231_PIN_AP_GPIO_AP_C17 = IOMUX_PIN(0, 2, 17, 21, 0, 9), + MXC91231_PIN_AP_ED_INT0 = IOMUX_PIN(0, 2, 18, 21, 1, 22), + MXC91231_PIN_AP_ED_INT1 = IOMUX_PIN(0, 2, 19, 21, 2, 22), + MXC91231_PIN_AP_ED_INT2 = IOMUX_PIN(0, 2, 20, 21, 3, 22), + MXC91231_PIN_AP_ED_INT3 = IOMUX_PIN(0, 2, 21, 22, 0, 22), + MXC91231_PIN_AP_ED_INT4 = IOMUX_PIN(0, 2, 22, 22, 1, 23), + MXC91231_PIN_AP_ED_INT5 = IOMUX_PIN(0, 2, 23, 22, 2, 23), + MXC91231_PIN_AP_ED_INT6 = IOMUX_PIN(0, 2, 24, 22, 3, 23), + MXC91231_PIN_AP_ED_INT7 = IOMUX_PIN(0, 2, 25, 23, 0, 23), + MXC91231_PIN_AP_U2_DSR_B = IOMUX_PIN(0, 2, 26, 23, 1, 28), + MXC91231_PIN_AP_U2_RI_B = IOMUX_PIN(0, 2, 27, 23, 2, 28), + MXC91231_PIN_AP_U2_CTS_B = IOMUX_PIN(0, 2, 28, 23, 3, 28), + MXC91231_PIN_AP_U2_DTR_B = IOMUX_PIN(0, 2, 29, 24, 0, 28), + MXC91231_PIN_AP_KPROW0 = IOMUX_PIN(0, 7, 0, 24, 1, 10), + MXC91231_PIN_AP_KPROW1 = IOMUX_PIN(0, 1, 15, 24, 2, 10), + MXC91231_PIN_AP_KPROW2 = IOMUX_PIN(0, 7, 0, 24, 3, 10), + MXC91231_PIN_AP_KPROW3 = IOMUX_PIN(0, 7, 0, 25, 0, 10), + MXC91231_PIN_AP_KPCOL0 = IOMUX_PIN(0, 7, 0, 25, 1, 11), + MXC91231_PIN_AP_KPCOL1 = IOMUX_PIN(0, 7, 0, 25, 2, 11), + MXC91231_PIN_AP_KPCOL2 = IOMUX_PIN(0, 7, 0, 25, 3, 11), + + /* Shared pins */ + MXC91231_PIN_SP_U3_TXD = IOMUX_PIN(1, 3, 0, 0, 0, 28), + MXC91231_PIN_SP_U3_RXD = IOMUX_PIN(1, 3, 1, 0, 1, 28), + MXC91231_PIN_SP_U3_RTS_B = IOMUX_PIN(1, 3, 2, 0, 2, 28), + MXC91231_PIN_SP_U3_CTS_B = IOMUX_PIN(1, 3, 3, 0, 3, 28), + MXC91231_PIN_SP_USB_TXOE_B = IOMUX_PIN(1, 3, 4, 1, 0, 28), + MXC91231_PIN_SP_USB_DAT_VP = IOMUX_PIN(1, 3, 5, 1, 1, 28), + MXC91231_PIN_SP_USB_SE0_VM = IOMUX_PIN(1, 3, 6, 1, 2, 28), + MXC91231_PIN_SP_USB_RXD = IOMUX_PIN(1, 3, 7, 1, 3, 28), + MXC91231_PIN_SP_UH2_TXOE_B = IOMUX_PIN(1, 3, 8, 2, 0, 28), + MXC91231_PIN_SP_UH2_SPEED = IOMUX_PIN(1, 3, 9, 2, 1, 28), + MXC91231_PIN_SP_UH2_SUSPEN = IOMUX_PIN(1, 3, 10, 2, 2, 28), + MXC91231_PIN_SP_UH2_TXDP = IOMUX_PIN(1, 3, 11, 2, 3, 28), + MXC91231_PIN_SP_UH2_RXDP = IOMUX_PIN(1, 3, 12, 3, 0, 28), + MXC91231_PIN_SP_UH2_RXDM = IOMUX_PIN(1, 3, 13, 3, 1, 28), + MXC91231_PIN_SP_UH2_OVR = IOMUX_PIN(1, 3, 14, 3, 2, 28), + MXC91231_PIN_SP_UH2_PWR = IOMUX_PIN(1, 3, 15, 3, 3, 28), + MXC91231_PIN_SP_SD1_DAT0 = IOMUX_PIN(1, 3, 16, 4, 0, 25), + MXC91231_PIN_SP_SD1_DAT1 = IOMUX_PIN(1, 3, 17, 4, 1, 25), + MXC91231_PIN_SP_SD1_DAT2 = IOMUX_PIN(1, 3, 18, 4, 2, 25), + MXC91231_PIN_SP_SD1_DAT3 = IOMUX_PIN(1, 3, 19, 4, 3, 25), + MXC91231_PIN_SP_SD1_CMD = IOMUX_PIN(1, 3, 20, 5, 0, 25), + MXC91231_PIN_SP_SD1_CLK = IOMUX_PIN(1, 3, 21, 5, 1, 25), + MXC91231_PIN_SP_SD2_DAT0 = IOMUX_PIN(1, 3, 22, 5, 2, 26), + MXC91231_PIN_SP_SD2_DAT1 = IOMUX_PIN(1, 3, 23, 5, 3, 26), + MXC91231_PIN_SP_SD2_DAT2 = IOMUX_PIN(1, 3, 24, 6, 0, 26), + MXC91231_PIN_SP_SD2_DAT3 = IOMUX_PIN(1, 3, 25, 6, 1, 26), + MXC91231_PIN_SP_GPIO_SP_A26 = IOMUX_PIN(1, 3, 26, 6, 2, 28), + MXC91231_PIN_SP_SPI1_CLK = IOMUX_PIN(1, 3, 27, 6, 3, 13), + MXC91231_PIN_SP_SPI1_MOSI = IOMUX_PIN(1, 3, 28, 7, 0, 13), + MXC91231_PIN_SP_SPI1_MISO = IOMUX_PIN(1, 3, 29, 7, 1, 13), + MXC91231_PIN_SP_SPI1_SS0 = IOMUX_PIN(1, 3, 30, 7, 2, 13), + MXC91231_PIN_SP_SPI1_SS1 = IOMUX_PIN(1, 3, 31, 7, 3, 13), + MXC91231_PIN_SP_SD2_CMD = IOMUX_PIN(1, 7, 0, 8, 0, 26), + MXC91231_PIN_SP_SD2_CLK = IOMUX_PIN(1, 7, 0, 8, 1, 26), + MXC91231_PIN_SP_SIM1_RST_B = IOMUX_PIN(1, 2, 30, 8, 2, 28), + MXC91231_PIN_SP_SIM1_SVEN = IOMUX_PIN(1, 7, 0, 8, 3, 28), + MXC91231_PIN_SP_SIM1_CLK = IOMUX_PIN(1, 7, 0, 9, 0, 28), + MXC91231_PIN_SP_SIM1_TRXD = IOMUX_PIN(1, 7, 0, 9, 1, 28), + MXC91231_PIN_SP_SIM1_PD = IOMUX_PIN(1, 2, 31, 9, 2, 28), + MXC91231_PIN_SP_UH2_TXDM = IOMUX_PIN(1, 7, 0, 9, 3, 28), + MXC91231_PIN_SP_UH2_RXD = IOMUX_PIN(1, 7, 0, 10, 0, 28), +}; + +#define PIN_AP_MAX (104) +#define PIN_SP_MAX (41) + +#define PIN_MAX (PIN_AP_MAX + PIN_SP_MAX) + +/* + * Convenience values for use with mxc_iomux_mode() + * + * Format here is MXC91231_PIN_(pin name)__(function) + */ + +#define MXC91231_PIN_SP_USB_DAT_VP__USB_DAT_VP \ + IOMUX_MODE(MXC91231_PIN_SP_USB_DAT_VP, IOMUX_CONFIG_FUNC) +#define MXC91231_PIN_SP_USB_SE0_VM__USB_SE0_VM \ + IOMUX_MODE(MXC91231_PIN_SP_USB_SE0_VM, IOMUX_CONFIG_FUNC) +#define MXC91231_PIN_SP_USB_DAT_VP__RXD2 \ + IOMUX_MODE(MXC91231_PIN_SP_USB_DAT_VP, IOMUX_CONFIG_ALT1) +#define MXC91231_PIN_SP_USB_SE0_VM__TXD2 \ + IOMUX_MODE(MXC91231_PIN_SP_USB_SE0_VM, IOMUX_CONFIG_ALT1) + + +#endif /* __MACH_IOMUX_MXC91231_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h index 7cd84547658f..a0fa40265468 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-v3.h +++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h @@ -68,28 +68,24 @@ struct pad_desc { /* * Use to set PAD control */ -#define PAD_CTL_DRIVE_VOLTAGE_3_3_V 0 -#define PAD_CTL_DRIVE_VOLTAGE_1_8_V 1 -#define PAD_CTL_NO_HYSTERESIS 0 -#define PAD_CTL_HYSTERESIS 1 +#define PAD_CTL_DVS (1 << 13) +#define PAD_CTL_HYS (1 << 8) -#define PAD_CTL_PULL_DISABLED 0x0 -#define PAD_CTL_PULL_KEEPER 0xa -#define PAD_CTL_PULL_DOWN_100K 0xc -#define PAD_CTL_PULL_UP_47K 0xd -#define PAD_CTL_PULL_UP_100K 0xe -#define PAD_CTL_PULL_UP_22K 0xf +#define PAD_CTL_PKE (1 << 7) +#define PAD_CTL_PUE (1 << 6) +#define PAD_CTL_PUS_100K_DOWN (0 << 4) +#define PAD_CTL_PUS_47K_UP (1 << 4) +#define PAD_CTL_PUS_100K_UP (2 << 4) +#define PAD_CTL_PUS_22K_UP (3 << 4) -#define PAD_CTL_OUTPUT_CMOS 0 -#define PAD_CTL_OUTPUT_OPEN_DRAIN 1 +#define PAD_CTL_ODE (1 << 3) -#define PAD_CTL_DRIVE_STRENGTH_NORM 0 -#define PAD_CTL_DRIVE_STRENGTH_HIGH 1 -#define PAD_CTL_DRIVE_STRENGTH_MAX 2 +#define PAD_CTL_DSE_STANDARD (0 << 1) +#define PAD_CTL_DSE_HIGH (1 << 1) +#define PAD_CTL_DSE_MAX (2 << 1) -#define PAD_CTL_SLEW_RATE_SLOW 0 -#define PAD_CTL_SLEW_RATE_FAST 1 +#define PAD_CTL_SRE_FAST (1 << 0) /* * setups a single pad: @@ -117,5 +113,10 @@ void mxc_iomux_v3_release_pad(struct pad_desc *pad); */ void mxc_iomux_v3_release_multiple_pads(struct pad_desc *pad_list, int count); +/* + * Initialise the iomux controller + */ +void mxc_iomux_v3_init(void __iomem *iomux_v3_base); + #endif /* __MACH_IOMUX_V3_H__*/ diff --git a/arch/arm/plat-mxc/include/mach/iomux.h b/arch/arm/plat-mxc/include/mach/iomux.h index 171f8adc1109..6d49f8ae3259 100644 --- a/arch/arm/plat-mxc/include/mach/iomux.h +++ b/arch/arm/plat-mxc/include/mach/iomux.h @@ -49,6 +49,9 @@ #ifdef CONFIG_ARCH_MX2 # define GPIO_PORT_MAX 5 #endif +#ifdef CONFIG_ARCH_MX25 +# define GPIO_PORT_MAX 3 +#endif #ifndef GPIO_PORT_MAX # error "GPIO config port count unknown!" @@ -107,6 +110,9 @@ #include <mach/iomux-mx27.h> #endif #endif +#ifdef CONFIG_ARCH_MX25 +#include <mach/iomux-mx25.h> +#endif /* decode irq number to use with IMR(x), ISR(x) and friends */ diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h index 518a36504b88..ead9d592168d 100644 --- a/arch/arm/plat-mxc/include/mach/irqs.h +++ b/arch/arm/plat-mxc/include/mach/irqs.h @@ -24,6 +24,10 @@ #define MXC_GPIO_IRQS (32 * 6) #elif defined CONFIG_ARCH_MX3 #define MXC_GPIO_IRQS (32 * 3) +#elif defined CONFIG_ARCH_MX25 +#define MXC_GPIO_IRQS (32 * 4) +#elif defined CONFIG_ARCH_MXC91231 +#define MXC_GPIO_IRQS (32 * 4) #endif /* diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h index 6065e00176ed..d3afafdcc0e5 100644 --- a/arch/arm/plat-mxc/include/mach/memory.h +++ b/arch/arm/plat-mxc/include/mach/memory.h @@ -22,6 +22,10 @@ #endif #elif defined CONFIG_ARCH_MX3 #define PHYS_OFFSET UL(0x80000000) +#elif defined CONFIG_ARCH_MX25 +#define PHYS_OFFSET UL(0x80000000) +#elif defined CONFIG_ARCH_MXC91231 +#define PHYS_OFFSET UL(0x90000000) #endif #if defined(CONFIG_MX1_VIDEO) diff --git a/arch/arm/plat-mxc/include/mach/mx1.h b/arch/arm/plat-mxc/include/mach/mx1.h index 1000bf330bcd..1b2890a5c452 100644 --- a/arch/arm/plat-mxc/include/mach/mx1.h +++ b/arch/arm/plat-mxc/include/mach/mx1.h @@ -12,10 +12,6 @@ #ifndef __ASM_ARCH_MXC_MX1_H__ #define __ASM_ARCH_MXC_MX1_H__ -#ifndef __ASM_ARCH_MXC_HARDWARE_H__ -#error "Do not include directly." -#endif - #include <mach/vmalloc.h> /* @@ -138,20 +134,6 @@ #define GPIO_INT_PORTD 62 #define WDT_INT 63 -/* gpio and gpio based interrupt handling */ -#define GPIO_DR 0x1C -#define GPIO_GDIR 0x00 -#define GPIO_PSR 0x24 -#define GPIO_ICR1 0x28 -#define GPIO_ICR2 0x2C -#define GPIO_IMR 0x30 -#define GPIO_ISR 0x34 -#define GPIO_INT_LOW_LEV 0x3 -#define GPIO_INT_HIGH_LEV 0x2 -#define GPIO_INT_RISE_EDGE 0x0 -#define GPIO_INT_FALL_EDGE 0x1 -#define GPIO_INT_NONE 0x4 - /* DMA */ #define DMA_REQ_UART3_T 2 #define DMA_REQ_UART3_R 3 @@ -179,8 +161,4 @@ #define DMA_REQ_UART1_T 30 #define DMA_REQ_UART1_R 31 -/* mandatory for CONFIG_DEBUG_LL */ -#define MXC_LL_UART_PADDR UART1_BASE_ADDR -#define MXC_LL_UART_VADDR IO_ADDRESS(UART1_BASE_ADDR) - #endif /* __ASM_ARCH_MXC_MX1_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx21.h b/arch/arm/plat-mxc/include/mach/mx21.h index 8b070a041a99..21112c695ec5 100644 --- a/arch/arm/plat-mxc/include/mach/mx21.h +++ b/arch/arm/plat-mxc/include/mach/mx21.h @@ -25,11 +25,6 @@ #ifndef __ASM_ARCH_MXC_MX21_H__ #define __ASM_ARCH_MXC_MX21_H__ -#ifndef __ASM_ARCH_MXC_HARDWARE_H__ -#error "Do not include directly." -#endif - - /* Memory regions and CS */ #define SDRAM_BASE_ADDR 0xC0000000 #define CSD1_BASE_ADDR 0xC4000000 diff --git a/arch/arm/plat-mxc/include/mach/mx25.h b/arch/arm/plat-mxc/include/mach/mx25.h new file mode 100644 index 000000000000..ec64bd9a8ab1 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mx25.h @@ -0,0 +1,44 @@ +#ifndef __MACH_MX25_H__ +#define __MACH_MX25_H__ + +#define MX25_AIPS1_BASE_ADDR 0x43F00000 +#define MX25_AIPS1_BASE_ADDR_VIRT 0xFC000000 +#define MX25_AIPS1_SIZE SZ_1M +#define MX25_AIPS2_BASE_ADDR 0x53F00000 +#define MX25_AIPS2_BASE_ADDR_VIRT 0xFC200000 +#define MX25_AIPS2_SIZE SZ_1M +#define MX25_AVIC_BASE_ADDR 0x68000000 +#define MX25_AVIC_BASE_ADDR_VIRT 0xFC400000 +#define MX25_AVIC_SIZE SZ_1M + +#define MX25_IOMUXC_BASE_ADDR (MX25_AIPS1_BASE_ADDR + 0xac000) + +#define MX25_CRM_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x80000) +#define MX25_GPT1_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0x90000) +#define MX25_WDOG_BASE_ADDR (MX25_AIPS2_BASE_ADDR + 0xdc000) + +#define MX25_GPIO1_BASE_ADDR_VIRT (MX25_AIPS2_BASE_ADDR_VIRT + 0xcc000) +#define MX25_GPIO2_BASE_ADDR_VIRT (MX25_AIPS2_BASE_ADDR_VIRT + 0xd0000) +#define MX25_GPIO3_BASE_ADDR_VIRT (MX25_AIPS2_BASE_ADDR_VIRT + 0xa4000) +#define MX25_GPIO4_BASE_ADDR_VIRT (MX25_AIPS2_BASE_ADDR_VIRT + 0x9c000) + +#define MX25_AIPS1_IO_ADDRESS(x) \ + (((x) - MX25_AIPS1_BASE_ADDR) + MX25_AIPS1_BASE_ADDR_VIRT) +#define MX25_AIPS2_IO_ADDRESS(x) \ + (((x) - MX25_AIPS2_BASE_ADDR) + MX25_AIPS2_BASE_ADDR_VIRT) +#define MX25_AVIC_IO_ADDRESS(x) \ + (((x) - MX25_AVIC_BASE_ADDR) + MX25_AVIC_BASE_ADDR_VIRT) + +#define __in_range(addr, name) ((addr) >= name##_BASE_ADDR && (addr) < name##_BASE_ADDR + name##_SIZE) + +#define MX25_IO_ADDRESS(x) \ + (void __force __iomem *) \ + (__in_range(x, MX25_AIPS1) ? MX25_AIPS1_IO_ADDRESS(x) : \ + __in_range(x, MX25_AIPS2) ? MX25_AIPS2_IO_ADDRESS(x) : \ + __in_range(x, MX25_AVIC) ? MX25_AVIC_IO_ADDRESS(x) : \ + 0xDEADBEEF) + +#define UART1_BASE_ADDR 0x43f90000 +#define UART2_BASE_ADDR 0x43f94000 + +#endif /* __MACH_MX25_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx27.h b/arch/arm/plat-mxc/include/mach/mx27.h index 6e93f2c0b7bb..dc3ad9aa952a 100644 --- a/arch/arm/plat-mxc/include/mach/mx27.h +++ b/arch/arm/plat-mxc/include/mach/mx27.h @@ -24,10 +24,6 @@ #ifndef __ASM_ARCH_MXC_MX27_H__ #define __ASM_ARCH_MXC_MX27_H__ -#ifndef __ASM_ARCH_MXC_HARDWARE_H__ -#error "Do not include directly." -#endif - /* IRAM */ #define IRAM_BASE_ADDR 0xFFFF4C00 /* internal ram */ @@ -120,7 +116,4 @@ extern int mx27_revision(void); /* Mandatory defines used globally */ -/* this CPU supports up to 192 GPIOs (don't forget the baseboard!) */ -#define ARCH_NR_GPIOS (192 + 16) - #endif /* __ASM_ARCH_MXC_MX27_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mx2x.h b/arch/arm/plat-mxc/include/mach/mx2x.h index fc40d3ab8c5b..db5d921e0fe6 100644 --- a/arch/arm/plat-mxc/include/mach/mx2x.h +++ b/arch/arm/plat-mxc/include/mach/mx2x.h @@ -23,10 +23,6 @@ #ifndef __ASM_ARCH_MXC_MX2x_H__ #define __ASM_ARCH_MXC_MX2x_H__ -#ifndef __ASM_ARCH_MXC_HARDWARE_H__ -#error "Do not include directly." -#endif - /* The following addresses are common between i.MX21 and i.MX27 */ /* Register offests */ @@ -154,20 +150,6 @@ #define MXC_INT_GPIO 8 #define MXC_INT_CSPI3 6 -/* gpio and gpio based interrupt handling */ -#define GPIO_DR 0x1C -#define GPIO_GDIR 0x00 -#define GPIO_PSR 0x24 -#define GPIO_ICR1 0x28 -#define GPIO_ICR2 0x2C -#define GPIO_IMR 0x30 -#define GPIO_ISR 0x34 -#define GPIO_INT_LOW_LEV 0x3 -#define GPIO_INT_HIGH_LEV 0x2 -#define GPIO_INT_RISE_EDGE 0x0 -#define GPIO_INT_FALL_EDGE 0x1 -#define GPIO_INT_NONE 0x4 - /* fixed DMA request numbers */ #define DMA_REQ_CSI_RX 31 #define DMA_REQ_CSI_STAT 30 diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h index 0b06941b6139..14ac0dcc82f4 100644 --- a/arch/arm/plat-mxc/include/mach/mx31.h +++ b/arch/arm/plat-mxc/include/mach/mx31.h @@ -4,7 +4,7 @@ #define MX31_IRAM_BASE_ADDR 0x1FFC0000 /* internal ram */ #define MX31_IRAM_SIZE SZ_16K -#define OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000) +#define MX31_OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000) #define ATA_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000) #define UART4_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B0000) #define UART5_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B4000) diff --git a/arch/arm/plat-mxc/include/mach/mx35.h b/arch/arm/plat-mxc/include/mach/mx35.h index 6465fefb42e3..ab4cfec6c8ab 100644 --- a/arch/arm/plat-mxc/include/mach/mx35.h +++ b/arch/arm/plat-mxc/include/mach/mx35.h @@ -5,6 +5,7 @@ #define MX35_IRAM_SIZE SZ_128K #define MXC_FEC_BASE_ADDR 0x50038000 +#define MX35_OTG_BASE_ADDR 0x53ff4000 #define MX35_NFC_BASE_ADDR 0xBB000000 /* diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h index b559a4bb5769..009f4440276b 100644 --- a/arch/arm/plat-mxc/include/mach/mx3x.h +++ b/arch/arm/plat-mxc/include/mach/mx3x.h @@ -11,10 +11,6 @@ #ifndef __ASM_ARCH_MXC_MX31_H__ #define __ASM_ARCH_MXC_MX31_H__ -#ifndef __ASM_ARCH_MXC_HARDWARE_H__ -#error "Do not include directly." -#endif - /* * MX31 memory map: * @@ -263,25 +259,8 @@ #define SYSTEM_REV_MIN CHIP_REV_1_0 #define SYSTEM_REV_NUM 3 -/* gpio and gpio based interrupt handling */ -#define GPIO_DR 0x00 -#define GPIO_GDIR 0x04 -#define GPIO_PSR 0x08 -#define GPIO_ICR1 0x0C -#define GPIO_ICR2 0x10 -#define GPIO_IMR 0x14 -#define GPIO_ISR 0x18 -#define GPIO_INT_LOW_LEV 0x0 -#define GPIO_INT_HIGH_LEV 0x1 -#define GPIO_INT_RISE_EDGE 0x2 -#define GPIO_INT_FALL_EDGE 0x3 -#define GPIO_INT_NONE 0x4 - /* Mandatory defines used globally */ -/* this CPU supports up to 96 GPIOs */ -#define ARCH_NR_GPIOS 96 - #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS) extern unsigned int system_rev; diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h index 5fa2a07f4eaf..51990536b845 100644 --- a/arch/arm/plat-mxc/include/mach/mxc.h +++ b/arch/arm/plat-mxc/include/mach/mxc.h @@ -26,9 +26,11 @@ #define MXC_CPU_MX1 1 #define MXC_CPU_MX21 21 +#define MXC_CPU_MX25 25 #define MXC_CPU_MX27 27 #define MXC_CPU_MX31 31 #define MXC_CPU_MX35 35 +#define MXC_CPU_MXC91231 91231 #ifndef __ASSEMBLY__ extern unsigned int __mxc_cpu_type; @@ -58,6 +60,18 @@ extern unsigned int __mxc_cpu_type; # define cpu_is_mx21() (0) #endif +#ifdef CONFIG_ARCH_MX25 +# ifdef mxc_cpu_type +# undef mxc_cpu_type +# define mxc_cpu_type __mxc_cpu_type +# else +# define mxc_cpu_type MXC_CPU_MX25 +# endif +# define cpu_is_mx25() (mxc_cpu_type == MXC_CPU_MX25) +#else +# define cpu_is_mx25() (0) +#endif + #ifdef CONFIG_MACH_MX27 # ifdef mxc_cpu_type # undef mxc_cpu_type @@ -94,13 +108,25 @@ extern unsigned int __mxc_cpu_type; # define cpu_is_mx35() (0) #endif +#ifdef CONFIG_ARCH_MXC91231 +# ifdef mxc_cpu_type +# undef mxc_cpu_type +# define mxc_cpu_type __mxc_cpu_type +# else +# define mxc_cpu_type MXC_CPU_MXC91231 +# endif +# define cpu_is_mxc91231() (mxc_cpu_type == MXC_CPU_MXC91231) +#else +# define cpu_is_mxc91231() (0) +#endif + #if defined(CONFIG_ARCH_MX3) || defined(CONFIG_ARCH_MX2) #define CSCR_U(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10) #define CSCR_L(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x4) #define CSCR_A(n) (IO_ADDRESS(WEIM_BASE_ADDR) + n * 0x10 + 0x8) #endif -#define cpu_is_mx3() (cpu_is_mx31() || cpu_is_mx35()) +#define cpu_is_mx3() (cpu_is_mx31() || cpu_is_mx35() || cpu_is_mxc91231()) #define cpu_is_mx2() (cpu_is_mx21() || cpu_is_mx27()) #endif /* __ASM_ARCH_MXC_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/mxc91231.h b/arch/arm/plat-mxc/include/mach/mxc91231.h new file mode 100644 index 000000000000..81484d1ef232 --- /dev/null +++ b/arch/arm/plat-mxc/include/mach/mxc91231.h @@ -0,0 +1,315 @@ +/* + * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. + * - Platform specific register memory map + * + * Copyright 2005-2007 Motorola, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MACH_MXC91231_H__ +#define __MACH_MXC91231_H__ + +/* + * L2CC + */ +#define MXC91231_L2CC_BASE_ADDR 0x30000000 +#define MXC91231_L2CC_BASE_ADDR_VIRT 0xF9000000 +#define MXC91231_L2CC_SIZE SZ_64K + +/* + * AIPS 1 + */ +#define MXC91231_AIPS1_BASE_ADDR 0x43F00000 +#define MXC91231_AIPS1_BASE_ADDR_VIRT 0xFC000000 +#define MXC91231_AIPS1_SIZE SZ_1M + +#define MXC91231_AIPS1_CTRL_BASE_ADDR MXC91231_AIPS1_BASE_ADDR +#define MXC91231_MAX_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x04000) +#define MXC91231_EVTMON_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x08000) +#define MXC91231_CLKCTL_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x0C000) +#define MXC91231_ETB_SLOT4_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x10000) +#define MXC91231_ETB_SLOT5_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x14000) +#define MXC91231_ECT_CTIO_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x18000) +#define MXC91231_I2C_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x80000) +#define MXC91231_MU_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x88000) +#define MXC91231_UART1_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x90000) +#define MXC91231_UART2_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x94000) +#define MXC91231_DSM_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x98000) +#define MXC91231_OWIRE_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0x9C000) +#define MXC91231_SSI1_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0xA0000) +#define MXC91231_KPP_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0xA8000) +#define MXC91231_IOMUX_AP_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0xAC000) +#define MXC91231_CTI_AP_BASE_ADDR (MXC91231_AIPS1_BASE_ADDR + 0xB8000) + +/* + * AIPS 2 + */ +#define MXC91231_AIPS2_BASE_ADDR 0x53F00000 +#define MXC91231_AIPS2_BASE_ADDR_VIRT 0xFC100000 +#define MXC91231_AIPS2_SIZE SZ_1M + +#define MXC91231_GEMK_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0x8C000) +#define MXC91231_GPT1_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0x90000) +#define MXC91231_EPIT1_AP_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0x94000) +#define MXC91231_SCC_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xAC000) +#define MXC91231_RNGA_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xB0000) +#define MXC91231_IPU_CTRL_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xC0000) +#define MXC91231_AUDMUX_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xC4000) +#define MXC91231_EDIO_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xC8000) +#define MXC91231_GPIO1_AP_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xCC000) +#define MXC91231_GPIO2_AP_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xD0000) +#define MXC91231_SDMA_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xD4000) +#define MXC91231_RTC_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xD8000) +#define MXC91231_WDOG1_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xDC000) +#define MXC91231_PWM_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xE0000) +#define MXC91231_GPIO3_AP_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xE4000) +#define MXC91231_WDOG2_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xE8000) +#define MXC91231_RTIC_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xEC000) +#define MXC91231_LPMC_BASE_ADDR (MXC91231_AIPS2_BASE_ADDR + 0xF0000) + +/* + * SPBA global module 0 + */ +#define MXC91231_SPBA0_BASE_ADDR 0x50000000 +#define MXC91231_SPBA0_BASE_ADDR_VIRT 0xFC200000 +#define MXC91231_SPBA0_SIZE SZ_1M + +#define MXC91231_MMC_SDHC1_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x04000) +#define MXC91231_MMC_SDHC2_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x08000) +#define MXC91231_UART3_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x0C000) +#define MXC91231_CSPI2_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x10000) +#define MXC91231_SSI2_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x14000) +#define MXC91231_SIM_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x18000) +#define MXC91231_IIM_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x1C000) +#define MXC91231_CTI_SDMA_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x20000) +#define MXC91231_USBOTG_CTRL_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x24000) +#define MXC91231_USBOTG_DATA_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x28000) +#define MXC91231_CSPI1_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x30000) +#define MXC91231_SPBA_CTRL_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x3C000) +#define MXC91231_IOMUX_COM_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x40000) +#define MXC91231_CRM_COM_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x44000) +#define MXC91231_CRM_AP_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x48000) +#define MXC91231_PLL0_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x4C000) +#define MXC91231_PLL1_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x50000) +#define MXC91231_PLL2_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x54000) +#define MXC91231_GPIO4_SH_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x58000) +#define MXC91231_HAC_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x5C000) +#define MXC91231_SAHARA_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x5C000) +#define MXC91231_PLL3_BASE_ADDR (MXC91231_SPBA0_BASE_ADDR + 0x60000) + +/* + * SPBA global module 1 + */ +#define MXC91231_SPBA1_BASE_ADDR 0x52000000 +#define MXC91231_SPBA1_BASE_ADDR_VIRT 0xFC300000 +#define MXC91231_SPBA1_SIZE SZ_1M + +#define MXC91231_MQSPI_BASE_ADDR (MXC91231_SPBA1_BASE_ADDR + 0x34000) +#define MXC91231_EL1T_BASE_ADDR (MXC91231_SPBA1_BASE_ADDR + 0x38000) + +/*! + * Defines for SPBA modules + */ +#define MXC91231_SPBA_SDHC1 0x04 +#define MXC91231_SPBA_SDHC2 0x08 +#define MXC91231_SPBA_UART3 0x0C +#define MXC91231_SPBA_CSPI2 0x10 +#define MXC91231_SPBA_SSI2 0x14 +#define MXC91231_SPBA_SIM 0x18 +#define MXC91231_SPBA_IIM 0x1C +#define MXC91231_SPBA_CTI_SDMA 0x20 +#define MXC91231_SPBA_USBOTG_CTRL_REGS 0x24 +#define MXC91231_SPBA_USBOTG_DATA_REGS 0x28 +#define MXC91231_SPBA_CSPI1 0x30 +#define MXC91231_SPBA_MQSPI 0x34 +#define MXC91231_SPBA_EL1T 0x38 +#define MXC91231_SPBA_IOMUX 0x40 +#define MXC91231_SPBA_CRM_COM 0x44 +#define MXC91231_SPBA_CRM_AP 0x48 +#define MXC91231_SPBA_PLL0 0x4C +#define MXC91231_SPBA_PLL1 0x50 +#define MXC91231_SPBA_PLL2 0x54 +#define MXC91231_SPBA_GPIO4 0x58 +#define MXC91231_SPBA_SAHARA 0x5C + +/* + * ROMP and AVIC + */ +#define MXC91231_ROMP_BASE_ADDR 0x60000000 +#define MXC91231_ROMP_BASE_ADDR_VIRT 0xFC400000 +#define MXC91231_ROMP_SIZE SZ_64K + +#define MXC91231_AVIC_BASE_ADDR 0x68000000 +#define MXC91231_AVIC_BASE_ADDR_VIRT 0xFC410000 +#define MXC91231_AVIC_SIZE SZ_64K + +/* + * NAND, SDRAM, WEIM, M3IF, EMI controllers + */ +#define MXC91231_X_MEMC_BASE_ADDR 0xB8000000 +#define MXC91231_X_MEMC_BASE_ADDR_VIRT 0xFC420000 +#define MXC91231_X_MEMC_SIZE SZ_64K + +#define MXC91231_NFC_BASE_ADDR (MXC91231_X_MEMC_BASE_ADDR + 0x0000) +#define MXC91231_ESDCTL_BASE_ADDR (MXC91231_X_MEMC_BASE_ADDR + 0x1000) +#define MXC91231_WEIM_BASE_ADDR (MXC91231_X_MEMC_BASE_ADDR + 0x2000) +#define MXC91231_M3IF_BASE_ADDR (MXC91231_X_MEMC_BASE_ADDR + 0x3000) +#define MXC91231_EMI_CTL_BASE_ADDR (MXC91231_X_MEMC_BASE_ADDR + 0x4000) + +/* + * Memory regions and CS + * CPLD is connected on CS4 + * CS5 is TP1021 or it is not connected + * */ +#define MXC91231_FB_RAM_BASE_ADDR 0x78000000 +#define MXC91231_FB_RAM_SIZE SZ_256K +#define MXC91231_CSD0_BASE_ADDR 0x80000000 +#define MXC91231_CSD1_BASE_ADDR 0x90000000 +#define MXC91231_CS0_BASE_ADDR 0xA0000000 +#define MXC91231_CS1_BASE_ADDR 0xA8000000 +#define MXC91231_CS2_BASE_ADDR 0xB0000000 +#define MXC91231_CS3_BASE_ADDR 0xB2000000 +#define MXC91231_CS4_BASE_ADDR 0xB4000000 +#define MXC91231_CS5_BASE_ADDR 0xB6000000 + +/* Is given address belongs to the specified memory region? */ +#define ADDRESS_IN_REGION(addr, start, size) \ + (((addr) >= (start)) && ((addr) < (start)+(size))) + +/* Is given address belongs to the specified named `module'? */ +#define MXC91231_IS_MODULE(addr, module) \ + ADDRESS_IN_REGION(addr, MXC91231_ ## module ## _BASE_ADDR, \ + MXC91231_ ## module ## _SIZE) +/* + * This macro defines the physical to virtual address mapping for all the + * peripheral modules. It is used by passing in the physical address as x + * and returning the virtual address. If the physical address is not mapped, + * it returns 0xDEADBEEF + */ + +#define MXC91231_IO_ADDRESS(x) \ + (void __iomem *) \ + (MXC91231_IS_MODULE(x, L2CC) ? MXC91231_L2CC_IO_ADDRESS(x) : \ + MXC91231_IS_MODULE(x, AIPS1) ? MXC91231_AIPS1_IO_ADDRESS(x) : \ + MXC91231_IS_MODULE(x, AIPS2) ? MXC91231_AIPS2_IO_ADDRESS(x) : \ + MXC91231_IS_MODULE(x, SPBA0) ? MXC91231_SPBA0_IO_ADDRESS(x) : \ + MXC91231_IS_MODULE(x, SPBA1) ? MXC91231_SPBA1_IO_ADDRESS(x) : \ + MXC91231_IS_MODULE(x, ROMP) ? MXC91231_ROMP_IO_ADDRESS(x) : \ + MXC91231_IS_MODULE(x, AVIC) ? MXC91231_AVIC_IO_ADDRESS(x) : \ + MXC91231_IS_MODULE(x, X_MEMC) ? MXC91231_X_MEMC_IO_ADDRESS(x) : \ + 0xDEADBEEF) + + +/* + * define the address mapping macros: in physical address order + */ +#define MXC91231_L2CC_IO_ADDRESS(x) \ + (((x) - MXC91231_L2CC_BASE_ADDR) + MXC91231_L2CC_BASE_ADDR_VIRT) + +#define MXC91231_AIPS1_IO_ADDRESS(x) \ + (((x) - MXC91231_AIPS1_BASE_ADDR) + MXC91231_AIPS1_BASE_ADDR_VIRT) + +#define MXC91231_SPBA0_IO_ADDRESS(x) \ + (((x) - MXC91231_SPBA0_BASE_ADDR) + MXC91231_SPBA0_BASE_ADDR_VIRT) + +#define MXC91231_SPBA1_IO_ADDRESS(x) \ + (((x) - MXC91231_SPBA1_BASE_ADDR) + MXC91231_SPBA1_BASE_ADDR_VIRT) + +#define MXC91231_AIPS2_IO_ADDRESS(x) \ + (((x) - MXC91231_AIPS2_BASE_ADDR) + MXC91231_AIPS2_BASE_ADDR_VIRT) + +#define MXC91231_ROMP_IO_ADDRESS(x) \ + (((x) - MXC91231_ROMP_BASE_ADDR) + MXC91231_ROMP_BASE_ADDR_VIRT) + +#define MXC91231_AVIC_IO_ADDRESS(x) \ + (((x) - MXC91231_AVIC_BASE_ADDR) + MXC91231_AVIC_BASE_ADDR_VIRT) + +#define MXC91231_X_MEMC_IO_ADDRESS(x) \ + (((x) - MXC91231_X_MEMC_BASE_ADDR) + MXC91231_X_MEMC_BASE_ADDR_VIRT) + +/* + * Interrupt numbers + */ +#define MXC91231_INT_GPIO3 0 +#define MXC91231_INT_EL1T_CI 1 +#define MXC91231_INT_EL1T_RFCI 2 +#define MXC91231_INT_EL1T_RFI 3 +#define MXC91231_INT_EL1T_MCU 4 +#define MXC91231_INT_EL1T_IPI 5 +#define MXC91231_INT_MU_GEN 6 +#define MXC91231_INT_GPIO4 7 +#define MXC91231_INT_MMC_SDHC2 8 +#define MXC91231_INT_MMC_SDHC1 9 +#define MXC91231_INT_I2C 10 +#define MXC91231_INT_SSI2 11 +#define MXC91231_INT_SSI1 12 +#define MXC91231_INT_CSPI2 13 +#define MXC91231_INT_CSPI1 14 +#define MXC91231_INT_RTIC 15 +#define MXC91231_INT_SAHARA 15 +#define MXC91231_INT_HAC 15 +#define MXC91231_INT_UART3_RX 16 +#define MXC91231_INT_UART3_TX 17 +#define MXC91231_INT_UART3_MINT 18 +#define MXC91231_INT_ECT 19 +#define MXC91231_INT_SIM_IPB 20 +#define MXC91231_INT_SIM_DATA 21 +#define MXC91231_INT_RNGA 22 +#define MXC91231_INT_DSM_AP 23 +#define MXC91231_INT_KPP 24 +#define MXC91231_INT_RTC 25 +#define MXC91231_INT_PWM 26 +#define MXC91231_INT_GEMK_AP 27 +#define MXC91231_INT_EPIT 28 +#define MXC91231_INT_GPT 29 +#define MXC91231_INT_UART2_RX 30 +#define MXC91231_INT_UART2_TX 31 +#define MXC91231_INT_UART2_MINT 32 +#define MXC91231_INT_NANDFC 33 +#define MXC91231_INT_SDMA 34 +#define MXC91231_INT_USB_WAKEUP 35 +#define MXC91231_INT_USB_SOF 36 +#define MXC91231_INT_PMU_EVTMON 37 +#define MXC91231_INT_USB_FUNC 38 +#define MXC91231_INT_USB_DMA 39 +#define MXC91231_INT_USB_CTRL 40 +#define MXC91231_INT_IPU_ERR 41 +#define MXC91231_INT_IPU_SYN 42 +#define MXC91231_INT_UART1_RX 43 +#define MXC91231_INT_UART1_TX 44 +#define MXC91231_INT_UART1_MINT 45 +#define MXC91231_INT_IIM 46 +#define MXC91231_INT_MU_RX_OR 47 +#define MXC91231_INT_MU_TX_OR 48 +#define MXC91231_INT_SCC_SCM 49 +#define MXC91231_INT_SCC_SMN 50 +#define MXC91231_INT_GPIO2 51 +#define MXC91231_INT_GPIO1 52 +#define MXC91231_INT_MQSPI1 53 +#define MXC91231_INT_MQSPI2 54 +#define MXC91231_INT_WDOG2 55 +#define MXC91231_INT_EXT_INT7 56 +#define MXC91231_INT_EXT_INT6 57 +#define MXC91231_INT_EXT_INT5 58 +#define MXC91231_INT_EXT_INT4 59 +#define MXC91231_INT_EXT_INT3 60 +#define MXC91231_INT_EXT_INT2 61 +#define MXC91231_INT_EXT_INT1 62 +#define MXC91231_INT_EXT_INT0 63 + +#define MXC91231_MAX_INT_LINES 63 +#define MXC91231_MAX_EXT_LINES 8 + +#endif /* __MACH_MXC91231_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h index e56241af870e..ef00199568de 100644 --- a/arch/arm/plat-mxc/include/mach/system.h +++ b/arch/arm/plat-mxc/include/mach/system.h @@ -21,8 +21,18 @@ #ifndef __ASM_ARCH_MXC_SYSTEM_H__ #define __ASM_ARCH_MXC_SYSTEM_H__ +#include <mach/hardware.h> +#include <mach/common.h> + static inline void arch_idle(void) { +#ifdef CONFIG_ARCH_MXC91231 + if (cpu_is_mxc91231()) { + /* Need this to set DSM low-power mode */ + mxc91231_prepare_idle(); + } +#endif + cpu_do_idle(); } diff --git a/arch/arm/plat-mxc/include/mach/timex.h b/arch/arm/plat-mxc/include/mach/timex.h index 07b4a73c9d2f..527a6c24788e 100644 --- a/arch/arm/plat-mxc/include/mach/timex.h +++ b/arch/arm/plat-mxc/include/mach/timex.h @@ -26,6 +26,10 @@ #define CLOCK_TICK_RATE 13300000 #elif defined CONFIG_ARCH_MX3 #define CLOCK_TICK_RATE 16625000 +#elif defined CONFIG_ARCH_MX25 +#define CLOCK_TICK_RATE 16000000 +#elif defined CONFIG_ARCH_MXC91231 +#define CLOCK_TICK_RATE 13000000 #endif #endif /* __ASM_ARCH_MXC_TIMEX_H__ */ diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h index de6fe0365982..082a3908256b 100644 --- a/arch/arm/plat-mxc/include/mach/uncompress.h +++ b/arch/arm/plat-mxc/include/mach/uncompress.h @@ -26,8 +26,11 @@ #define __MXC_BOOT_UNCOMPRESS #include <mach/hardware.h> +#include <asm/mach-types.h> -#define UART(x) (*(volatile unsigned long *)(serial_port + (x))) +static unsigned long uart_base; + +#define UART(x) (*(volatile unsigned long *)(uart_base + (x))) #define USR2 0x98 #define USR2_TXFE (1<<14) @@ -46,19 +49,10 @@ static void putc(int ch) { - static unsigned long serial_port = 0; - - if (unlikely(serial_port == 0)) { - do { - serial_port = UART1_BASE_ADDR; - if (UART(UCR1) & UCR1_UARTEN) - break; - serial_port = UART2_BASE_ADDR; - if (UART(UCR1) & UCR1_UARTEN) - break; - return; - } while (0); - } + if (!uart_base) + return; + if (!(UART(UCR1) & UCR1_UARTEN)) + return; while (!(UART(USR2) & USR2_TXFE)) barrier(); @@ -68,11 +62,49 @@ static void putc(int ch) #define flush() do { } while (0) -/* - * nothing to do - */ -#define arch_decomp_setup() +#define MX1_UART1_BASE_ADDR 0x00206000 +#define MX25_UART1_BASE_ADDR 0x43f90000 +#define MX2X_UART1_BASE_ADDR 0x1000a000 +#define MX3X_UART1_BASE_ADDR 0x43F90000 +#define MX3X_UART2_BASE_ADDR 0x43F94000 + +static __inline__ void __arch_decomp_setup(unsigned long arch_id) +{ + switch (arch_id) { + case MACH_TYPE_MX1ADS: + case MACH_TYPE_SCB9328: + uart_base = MX1_UART1_BASE_ADDR; + break; + case MACH_TYPE_MX25_3DS: + uart_base = MX25_UART1_BASE_ADDR; + break; + case MACH_TYPE_IMX27LITE: + case MACH_TYPE_MX27_3DS: + case MACH_TYPE_MX27ADS: + case MACH_TYPE_PCM038: + case MACH_TYPE_MX21ADS: + uart_base = MX2X_UART1_BASE_ADDR; + break; + case MACH_TYPE_MX31LITE: + case MACH_TYPE_ARMADILLO5X0: + case MACH_TYPE_MX31MOBOARD: + case MACH_TYPE_QONG: + case MACH_TYPE_MX31_3DS: + case MACH_TYPE_PCM037: + case MACH_TYPE_MX31ADS: + case MACH_TYPE_MX35_3DS: + case MACH_TYPE_PCM043: + uart_base = MX3X_UART1_BASE_ADDR; + break; + case MACH_TYPE_MAGX_ZN5: + uart_base = MX3X_UART2_BASE_ADDR; + break; + default: + break; + } +} +#define arch_decomp_setup() __arch_decomp_setup(arch_id) #define arch_decomp_wdog() #endif /* __ASM_ARCH_MXC_UNCOMPRESS_H__ */ diff --git a/arch/arm/plat-mxc/iomux-v3.c b/arch/arm/plat-mxc/iomux-v3.c index 77a078f9513f..851ca99bf1b1 100644 --- a/arch/arm/plat-mxc/iomux-v3.c +++ b/arch/arm/plat-mxc/iomux-v3.c @@ -29,7 +29,7 @@ #include <asm/mach/map.h> #include <mach/iomux-v3.h> -#define IOMUX_BASE IO_ADDRESS(IOMUXC_BASE_ADDR) +static void __iomem *base; static unsigned long iomux_v3_pad_alloc_map[0x200 / BITS_PER_LONG]; @@ -45,14 +45,14 @@ int mxc_iomux_v3_setup_pad(struct pad_desc *pad) if (test_and_set_bit(pad_ofs >> 2, iomux_v3_pad_alloc_map)) return -EBUSY; if (pad->mux_ctrl_ofs) - __raw_writel(pad->mux_mode, IOMUX_BASE + pad->mux_ctrl_ofs); + __raw_writel(pad->mux_mode, base + pad->mux_ctrl_ofs); if (pad->select_input_ofs) __raw_writel(pad->select_input, - IOMUX_BASE + pad->select_input_ofs); + base + pad->select_input_ofs); - if (!(pad->pad_ctrl & NO_PAD_CTRL)) - __raw_writel(pad->pad_ctrl, IOMUX_BASE + pad->pad_ctrl_ofs); + if (!(pad->pad_ctrl & NO_PAD_CTRL) && pad->pad_ctrl_ofs) + __raw_writel(pad->pad_ctrl, base + pad->pad_ctrl_ofs); return 0; } EXPORT_SYMBOL(mxc_iomux_v3_setup_pad); @@ -96,3 +96,8 @@ void mxc_iomux_v3_release_multiple_pads(struct pad_desc *pad_list, int count) } } EXPORT_SYMBOL(mxc_iomux_v3_release_multiple_pads); + +void mxc_iomux_v3_init(void __iomem *iomux_v3_base) +{ + base = iomux_v3_base; +} diff --git a/arch/arm/plat-mxc/irq.c b/arch/arm/plat-mxc/irq.c index 8aee76304f8f..778ddfe57d89 100644 --- a/arch/arm/plat-mxc/irq.c +++ b/arch/arm/plat-mxc/irq.c @@ -44,7 +44,7 @@ #define AVIC_FIPNDH 0x60 /* fast int pending high */ #define AVIC_FIPNDL 0x64 /* fast int pending low */ -static void __iomem *avic_base; +void __iomem *avic_base; int imx_irq_set_priority(unsigned char irq, unsigned char prio) { @@ -113,11 +113,11 @@ static struct irq_chip mxc_avic_chip = { * interrupts. It registers the interrupt enable and disable functions * to the kernel for each interrupt source. */ -void __init mxc_init_irq(void) +void __init mxc_init_irq(void __iomem *irqbase) { int i; - avic_base = IO_ADDRESS(AVIC_BASE_ADDR); + avic_base = irqbase; /* put the AVIC into the reset value with * all interrupts disabled diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c index ae34198a79dd..5cdbd605ac05 100644 --- a/arch/arm/plat-mxc/pwm.c +++ b/arch/arm/plat-mxc/pwm.c @@ -32,6 +32,7 @@ #define MX3_PWMPR 0x10 /* PWM Period Register */ #define MX3_PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4) #define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16) +#define MX3_PWMCR_CLKSRC_IPG (1 << 16) #define MX3_PWMCR_EN (1 << 0) @@ -55,9 +56,11 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) return -EINVAL; - if (cpu_is_mx27() || cpu_is_mx3()) { + if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25()) { unsigned long long c; unsigned long period_cycles, duty_cycles, prescale; + u32 cr; + c = clk_get_rate(pwm->clk); c = c * period_ns; do_div(c, 1000000000); @@ -72,9 +75,15 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR); writel(period_cycles, pwm->mmio_base + MX3_PWMPR); - writel(MX3_PWMCR_PRESCALER(prescale - 1) | - MX3_PWMCR_CLKSRC_IPG_HIGH | MX3_PWMCR_EN, - pwm->mmio_base + MX3_PWMCR); + + cr = MX3_PWMCR_PRESCALER(prescale) | MX3_PWMCR_EN; + + if (cpu_is_mx25()) + cr |= MX3_PWMCR_CLKSRC_IPG; + else + cr |= MX3_PWMCR_CLKSRC_IPG_HIGH; + + writel(cr, pwm->mmio_base + MX3_PWMCR); } else if (cpu_is_mx1() || cpu_is_mx21()) { /* The PWM subsystem allows for exact frequencies. However, * I cannot connect a scope on my device to the PWM line and @@ -118,6 +127,8 @@ EXPORT_SYMBOL(pwm_enable); void pwm_disable(struct pwm_device *pwm) { + writel(0, pwm->mmio_base + MX3_PWMCR); + if (pwm->clk_enabled) { clk_disable(pwm->clk); pwm->clk_enabled = 0; diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c index 79c37577c916..97f42799fa58 100644 --- a/arch/arm/plat-mxc/system.c +++ b/arch/arm/plat-mxc/system.c @@ -27,32 +27,38 @@ #include <linux/delay.h> #include <mach/hardware.h> +#include <mach/common.h> #include <asm/proc-fns.h> #include <asm/system.h> -#ifdef CONFIG_ARCH_MX1 -#define WDOG_WCR_REG IO_ADDRESS(WDT_BASE_ADDR) -#define WDOG_WCR_ENABLE (1 << 0) -#else -#define WDOG_WCR_REG IO_ADDRESS(WDOG_BASE_ADDR) -#define WDOG_WCR_ENABLE (1 << 2) -#endif +static void __iomem *wdog_base; /* * Reset the system. It is called by machine_restart(). */ void arch_reset(char mode, const char *cmd) { - if (!cpu_is_mx1()) { + unsigned int wcr_enable; + +#ifdef CONFIG_ARCH_MXC91231 + if (cpu_is_mxc91231()) { + mxc91231_arch_reset(mode, cmd); + return; + } +#endif + if (cpu_is_mx1()) { + wcr_enable = (1 << 0); + } else { struct clk *clk; clk = clk_get_sys("imx-wdt.0", NULL); if (!IS_ERR(clk)) clk_enable(clk); + wcr_enable = (1 << 2); } /* Assert SRS signal */ - __raw_writew(WDOG_WCR_ENABLE, WDOG_WCR_REG); + __raw_writew(wcr_enable, wdog_base); /* wait for reset to assert... */ mdelay(500); @@ -65,3 +71,8 @@ void arch_reset(char mode, const char *cmd) /* we'll take a jump through zero as a poor second */ cpu_reset(0); } + +void mxc_arch_reset_init(void __iomem *base) +{ + wdog_base = base; +} diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 88fb3a57e029..844567ee35fe 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c @@ -47,7 +47,7 @@ #define MX2_TSTAT_CAPT (1 << 1) #define MX2_TSTAT_COMP (1 << 0) -/* MX31, MX35 */ +/* MX31, MX35, MX25, MXC91231 */ #define MX3_TCTL_WAITEN (1 << 3) #define MX3_TCTL_CLK_IPG (1 << 6) #define MX3_TCTL_FRR (1 << 9) @@ -66,7 +66,7 @@ static inline void gpt_irq_disable(void) { unsigned int tmp; - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) __raw_writel(0, timer_base + MX3_IR); else { tmp = __raw_readl(timer_base + MXC_TCTL); @@ -76,7 +76,7 @@ static inline void gpt_irq_disable(void) static inline void gpt_irq_enable(void) { - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) __raw_writel(1<<0, timer_base + MX3_IR); else { __raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN, @@ -90,7 +90,7 @@ static void gpt_irq_acknowledge(void) __raw_writel(0, timer_base + MX1_2_TSTAT); if (cpu_is_mx2()) __raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT); - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) __raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT); } @@ -117,7 +117,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk) { unsigned int c = clk_get_rate(timer_clk); - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) clocksource_mxc.read = mx3_get_cycles; clocksource_mxc.mult = clocksource_hz2mult(c, @@ -180,7 +180,7 @@ static void mxc_set_mode(enum clock_event_mode mode, if (mode != clockevent_mode) { /* Set event time into far-far future */ - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) __raw_writel(__raw_readl(timer_base + MX3_TCN) - 3, timer_base + MX3_TCMP); else @@ -233,7 +233,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id) struct clock_event_device *evt = &clockevent_mxc; uint32_t tstat; - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) tstat = __raw_readl(timer_base + MX3_TSTAT); else tstat = __raw_readl(timer_base + MX1_2_TSTAT); @@ -264,7 +264,7 @@ static int __init mxc_clockevent_init(struct clk *timer_clk) { unsigned int c = clk_get_rate(timer_clk); - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) clockevent_mxc.set_next_event = mx3_set_next_event; clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC, @@ -281,30 +281,13 @@ static int __init mxc_clockevent_init(struct clk *timer_clk) return 0; } -void __init mxc_timer_init(struct clk *timer_clk) +void __init mxc_timer_init(struct clk *timer_clk, void __iomem *base, int irq) { uint32_t tctl_val; - int irq; clk_enable(timer_clk); - if (cpu_is_mx1()) { -#ifdef CONFIG_ARCH_MX1 - timer_base = IO_ADDRESS(TIM1_BASE_ADDR); - irq = TIM1_INT; -#endif - } else if (cpu_is_mx2()) { -#ifdef CONFIG_ARCH_MX2 - timer_base = IO_ADDRESS(GPT1_BASE_ADDR); - irq = MXC_INT_GPT1; -#endif - } else if (cpu_is_mx3()) { -#ifdef CONFIG_ARCH_MX3 - timer_base = IO_ADDRESS(GPT1_BASE_ADDR); - irq = MXC_INT_GPT; -#endif - } else - BUG(); + timer_base = base; /* * Initialise to a known state (all timers off, and timing reset) @@ -313,7 +296,7 @@ void __init mxc_timer_init(struct clk *timer_clk) __raw_writel(0, timer_base + MXC_TCTL); __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */ - if (cpu_is_mx3()) + if (cpu_is_mx3() || cpu_is_mx25()) tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN; else tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c index 843e8af64066..1868c0d8f9b5 100644 --- a/arch/arm/plat-omap/cpu-omap.c +++ b/arch/arm/plat-omap/cpu-omap.c @@ -78,10 +78,10 @@ static int omap_target(struct cpufreq_policy *policy, /* Ensure desired rate is within allowed range. Some govenors * (ondemand) will just pass target_freq=0 to get the minimum. */ - if (target_freq < policy->cpuinfo.min_freq) - target_freq = policy->cpuinfo.min_freq; - if (target_freq > policy->cpuinfo.max_freq) - target_freq = policy->cpuinfo.max_freq; + if (target_freq < policy->min) + target_freq = policy->min; + if (target_freq > policy->max) + target_freq = policy->max; freqs.old = omap_getspeed(0); freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000; diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 26b387c12423..00940dc6bb50 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -138,6 +138,32 @@ #define OMAP24XX_GPIO_CLEARDATAOUT 0x0090 #define OMAP24XX_GPIO_SETDATAOUT 0x0094 +#define OMAP4_GPIO_REVISION 0x0000 +#define OMAP4_GPIO_SYSCONFIG 0x0010 +#define OMAP4_GPIO_EOI 0x0020 +#define OMAP4_GPIO_IRQSTATUSRAW0 0x0024 +#define OMAP4_GPIO_IRQSTATUSRAW1 0x0028 +#define OMAP4_GPIO_IRQSTATUS0 0x002c +#define OMAP4_GPIO_IRQSTATUS1 0x0030 +#define OMAP4_GPIO_IRQSTATUSSET0 0x0034 +#define OMAP4_GPIO_IRQSTATUSSET1 0x0038 +#define OMAP4_GPIO_IRQSTATUSCLR0 0x003c +#define OMAP4_GPIO_IRQSTATUSCLR1 0x0040 +#define OMAP4_GPIO_IRQWAKEN0 0x0044 +#define OMAP4_GPIO_IRQWAKEN1 0x0048 +#define OMAP4_GPIO_SYSSTATUS 0x0104 +#define OMAP4_GPIO_CTRL 0x0130 +#define OMAP4_GPIO_OE 0x0134 +#define OMAP4_GPIO_DATAIN 0x0138 +#define OMAP4_GPIO_DATAOUT 0x013c +#define OMAP4_GPIO_LEVELDETECT0 0x0140 +#define OMAP4_GPIO_LEVELDETECT1 0x0144 +#define OMAP4_GPIO_RISINGDETECT 0x0148 +#define OMAP4_GPIO_FALLINGDETECT 0x014c +#define OMAP4_GPIO_DEBOUNCENABLE 0x0150 +#define OMAP4_GPIO_DEBOUNCINGTIME 0x0154 +#define OMAP4_GPIO_CLEARDATAOUT 0x0190 +#define OMAP4_GPIO_SETDATAOUT 0x0194 /* * omap34xx specific GPIO registers */ @@ -386,12 +412,16 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) reg += OMAP850_GPIO_DIR_CONTROL; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_OE; break; #endif +#if defined(CONFIG_ARCH_OMAP4) + case METHOD_GPIO_24XX: + reg += OMAP4_GPIO_OE; + break; +#endif default: WARN_ON(1); return; @@ -459,8 +489,7 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) l &= ~(1 << gpio); break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: if (enable) reg += OMAP24XX_GPIO_SETDATAOUT; @@ -469,6 +498,15 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) l = 1 << gpio; break; #endif +#ifdef CONFIG_ARCH_OMAP4 + case METHOD_GPIO_24XX: + if (enable) + reg += OMAP4_GPIO_SETDATAOUT; + else + reg += OMAP4_GPIO_CLEARDATAOUT; + l = 1 << gpio; + break; +#endif default: WARN_ON(1); return; @@ -511,12 +549,16 @@ static int __omap_get_gpio_datain(int gpio) reg += OMAP850_GPIO_DATA_INPUT; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_DATAIN; break; #endif +#ifdef CONFIG_ARCH_OMAP4 + case METHOD_GPIO_24XX: + reg += OMAP4_GPIO_DATAIN; + break; +#endif default: return -EINVAL; } @@ -544,7 +586,11 @@ void omap_set_gpio_debounce(int gpio, int enable) bank = get_gpio_bank(gpio); reg = bank->base; +#ifdef CONFIG_ARCH_OMAP4 + reg += OMAP4_GPIO_DEBOUNCENABLE; +#else reg += OMAP24XX_GPIO_DEBOUNCE_EN; +#endif spin_lock_irqsave(&bank->lock, flags); val = __raw_readl(reg); @@ -581,7 +627,11 @@ void omap_set_gpio_debounce_time(int gpio, int enc_time) reg = bank->base; enc_time &= 0xff; +#ifdef CONFIG_ARCH_OMAP4 + reg += OMAP4_GPIO_DEBOUNCINGTIME; +#else reg += OMAP24XX_GPIO_DEBOUNCE_VAL; +#endif __raw_writel(enc_time, reg); } EXPORT_SYMBOL(omap_set_gpio_debounce_time); @@ -593,23 +643,46 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, { void __iomem *base = bank->base; u32 gpio_bit = 1 << gpio; + u32 val; - MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, - trigger & IRQ_TYPE_LEVEL_LOW); - MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, - trigger & IRQ_TYPE_LEVEL_HIGH); - MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_RISING); - MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, - trigger & IRQ_TYPE_EDGE_FALLING); - + if (cpu_is_omap44xx()) { + MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit, + trigger & IRQ_TYPE_LEVEL_LOW); + MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit, + trigger & IRQ_TYPE_LEVEL_HIGH); + MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_RISING); + MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_FALLING); + } else { + MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, + trigger & IRQ_TYPE_LEVEL_LOW); + MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, + trigger & IRQ_TYPE_LEVEL_HIGH); + MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_RISING); + MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, + trigger & IRQ_TYPE_EDGE_FALLING); + } if (likely(!(bank->non_wakeup_gpios & gpio_bit))) { - if (trigger != 0) - __raw_writel(1 << gpio, bank->base + if (cpu_is_omap44xx()) { + if (trigger != 0) + __raw_writel(1 << gpio, bank->base+ + OMAP4_GPIO_IRQWAKEN0); + else { + val = __raw_readl(bank->base + + OMAP4_GPIO_IRQWAKEN0); + __raw_writel(val & (~(1 << gpio)), bank->base + + OMAP4_GPIO_IRQWAKEN0); + } + } else { + if (trigger != 0) + __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_SETWKUENA); - else - __raw_writel(1 << gpio, bank->base + else + __raw_writel(1 << gpio, bank->base + OMAP24XX_GPIO_CLEARWKUENA); + } } else { if (trigger != 0) bank->enabled_non_wakeup_gpios |= gpio_bit; @@ -617,9 +690,15 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, bank->enabled_non_wakeup_gpios &= ~gpio_bit; } - bank->level_mask = - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) | - __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); + if (cpu_is_omap44xx()) { + bank->level_mask = + __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT0) | + __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT1); + } else { + bank->level_mask = + __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) | + __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); + } } #endif @@ -783,12 +862,16 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) reg += OMAP850_GPIO_INT_STATUS; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_IRQSTATUS1; break; #endif +#if defined(CONFIG_ARCH_OMAP4) + case METHOD_GPIO_24XX: + reg += OMAP4_GPIO_IRQSTATUS0; + break; +#endif default: WARN_ON(1); return; @@ -798,12 +881,16 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) /* Workaround for clearing DSP GPIO interrupts to allow retention */ #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2; - if (cpu_is_omap24xx() || cpu_is_omap34xx()) +#endif +#if defined(CONFIG_ARCH_OMAP4) + reg = bank->base + OMAP4_GPIO_IRQSTATUS1; +#endif + if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) { __raw_writel(gpio_mask, reg); /* Flush posted write for the irq status to avoid spurious interrupts */ __raw_readl(reg); -#endif + } } static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) @@ -853,13 +940,18 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) inv = 1; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_IRQENABLE1; mask = 0xffffffff; break; #endif +#if defined(CONFIG_ARCH_OMAP4) + case METHOD_GPIO_24XX: + reg += OMAP4_GPIO_IRQSTATUSSET0; + mask = 0xffffffff; + break; +#endif default: WARN_ON(1); return 0; @@ -927,8 +1019,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab l |= gpio_mask; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: if (enable) reg += OMAP24XX_GPIO_SETIRQENABLE1; @@ -937,6 +1028,15 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab l = gpio_mask; break; #endif +#ifdef CONFIG_ARCH_OMAP4 + case METHOD_GPIO_24XX: + if (enable) + reg += OMAP4_GPIO_IRQSTATUSSET0; + else + reg += OMAP4_GPIO_IRQSTATUSCLR0; + l = gpio_mask; + break; +#endif default: WARN_ON(1); return; @@ -1112,11 +1212,14 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (bank->method == METHOD_GPIO_850) isr_reg = bank->base + OMAP850_GPIO_INT_STATUS; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) if (bank->method == METHOD_GPIO_24XX) isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; #endif +#if defined(CONFIG_ARCH_OMAP4) + if (bank->method == METHOD_GPIO_24XX) + isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0; +#endif while(1) { u32 isr_saved, level_mask = 0; u32 enabled; @@ -1189,6 +1292,7 @@ static void gpio_mask_irq(unsigned int irq) struct gpio_bank *bank = get_irq_chip_data(irq); _set_gpio_irqenable(bank, gpio, 0); + _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE); } static void gpio_unmask_irq(unsigned int irq) @@ -1196,6 +1300,11 @@ static void gpio_unmask_irq(unsigned int irq) unsigned int gpio = irq - IH_GPIO_BASE; struct gpio_bank *bank = get_irq_chip_data(irq); unsigned int irq_mask = 1 << get_gpio_index(gpio); + struct irq_desc *desc = irq_to_desc(irq); + u32 trigger = desc->status & IRQ_TYPE_SENSE_MASK; + + if (trigger) + _set_gpio_triggering(bank, get_gpio_index(gpio), trigger); /* For level-triggered GPIOs, the clearing must be done after * the HW source is cleared, thus after the handler has run */ @@ -1547,7 +1656,7 @@ static int __init _omap_gpio_init(void) gpio_bank_count = OMAP34XX_NR_GPIOS; gpio_bank = gpio_bank_44xx; - rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION); + rev = __raw_readl(gpio_bank[0].base + OMAP4_GPIO_REVISION); printk(KERN_INFO "OMAP44xx GPIO hardware version %d.%d\n", (rev >> 4) & 0x0f, rev & 0x0f); } @@ -1581,7 +1690,16 @@ static int __init _omap_gpio_init(void) static const u32 non_wakeup_gpios[] = { 0xe203ffc0, 0x08700040 }; - + if (cpu_is_omap44xx()) { + __raw_writel(0xffffffff, bank->base + + OMAP4_GPIO_IRQSTATUSCLR0); + __raw_writew(0x0015, bank->base + + OMAP4_GPIO_SYSCONFIG); + __raw_writel(0x00000000, bank->base + + OMAP4_GPIO_DEBOUNCENABLE); + /* Initialize interface clock ungated, module enabled */ + __raw_writel(0, bank->base + OMAP4_GPIO_CTRL); + } else { __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1); __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1); __raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG); @@ -1589,12 +1707,12 @@ static int __init _omap_gpio_init(void) /* Initialize interface clock ungated, module enabled */ __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); + } if (i < ARRAY_SIZE(non_wakeup_gpios)) bank->non_wakeup_gpios = non_wakeup_gpios[i]; gpio_count = 32; } #endif - /* REVISIT eventually switch from OMAP-specific gpio structs * over to the generic ones */ @@ -1680,14 +1798,20 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg) wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN; wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; break; #endif +#ifdef CONFIG_ARCH_OMAP4 + case METHOD_GPIO_24XX: + wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0; + wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0; + wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0; + break; +#endif default: continue; } @@ -1722,13 +1846,18 @@ static int omap_gpio_resume(struct sys_device *dev) wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; break; #endif +#ifdef CONFIG_ARCH_OMAP4 + case METHOD_GPIO_24XX: + wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0; + wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0; + break; +#endif default: continue; } @@ -1772,21 +1901,29 @@ void omap2_gpio_prepare_for_retention(void) if (!(bank->enabled_non_wakeup_gpios)) continue; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) bank->saved_datain = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); #endif +#ifdef CONFIG_ARCH_OMAP4 + bank->saved_datain = __raw_readl(bank->base + + OMAP4_GPIO_DATAIN); + l1 = __raw_readl(bank->base + OMAP4_GPIO_FALLINGDETECT); + l2 = __raw_readl(bank->base + OMAP4_GPIO_RISINGDETECT); +#endif bank->saved_fallingdetect = l1; bank->saved_risingdetect = l2; l1 &= ~bank->enabled_non_wakeup_gpios; l2 &= ~bank->enabled_non_wakeup_gpios; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) __raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT); __raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT); #endif +#ifdef CONFIG_ARCH_OMAP4 + __raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT); + __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT); +#endif c++; } if (!c) { @@ -1808,27 +1945,29 @@ void omap2_gpio_resume_after_retention(void) if (!(bank->enabled_non_wakeup_gpios)) continue; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) __raw_writel(bank->saved_fallingdetect, bank->base + OMAP24XX_GPIO_FALLINGDETECT); __raw_writel(bank->saved_risingdetect, bank->base + OMAP24XX_GPIO_RISINGDETECT); + l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); +#endif +#ifdef CONFIG_ARCH_OMAP4 + __raw_writel(bank->saved_fallingdetect, + bank->base + OMAP4_GPIO_FALLINGDETECT); + __raw_writel(bank->saved_risingdetect, + bank->base + OMAP4_GPIO_RISINGDETECT); + l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN); #endif /* Check if any of the non-wakeup interrupt GPIOs have changed * state. If so, generate an IRQ by software. This is * horribly racy, but it's the best we can do to work around * this silicon bug. */ -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) - l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); -#endif l ^= bank->saved_datain; l &= bank->non_wakeup_gpios; if (l) { u32 old0, old1; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); __raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0); @@ -1836,6 +1975,20 @@ void omap2_gpio_resume_after_retention(void) __raw_writel(old0, bank->base + OMAP24XX_GPIO_LEVELDETECT0); __raw_writel(old1, bank->base + OMAP24XX_GPIO_LEVELDETECT1); #endif +#ifdef CONFIG_ARCH_OMAP4 + old0 = __raw_readl(bank->base + + OMAP4_GPIO_LEVELDETECT0); + old1 = __raw_readl(bank->base + + OMAP4_GPIO_LEVELDETECT1); + __raw_writel(old0 | l, bank->base + + OMAP4_GPIO_LEVELDETECT0); + __raw_writel(old1 | l, bank->base + + OMAP4_GPIO_LEVELDETECT1); + __raw_writel(old0, bank->base + + OMAP4_GPIO_LEVELDETECT0); + __raw_writel(old1, bank->base + + OMAP4_GPIO_LEVELDETECT1); +#endif } } diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h index 7b939cc01962..72f680b7180d 100644 --- a/arch/arm/plat-omap/include/mach/dma.h +++ b/arch/arm/plat-omap/include/mach/dma.h @@ -122,6 +122,11 @@ #define OMAP_DMA4_CCFN(n) (0x60 * (n) + 0xc0) #define OMAP_DMA4_COLOR(n) (0x60 * (n) + 0xc4) +/* Additional registers available on OMAP4 */ +#define OMAP_DMA4_CDP(n) (0x60 * (n) + 0xd0) +#define OMAP_DMA4_CNDP(n) (0x60 * (n) + 0xd4) +#define OMAP_DMA4_CCDN(n) (0x60 * (n) + 0xd8) + /* Dummy defines to keep multi-omap compiles happy */ #define OMAP1_DMA_REVISION 0 #define OMAP1_DMA_IRQSTATUS_L0 0 @@ -311,6 +316,89 @@ #define OMAP34XX_DMA_USIM_TX 79 /* S_DMA_78 */ #define OMAP34XX_DMA_USIM_RX 80 /* S_DMA_79 */ +/* DMA request lines for 44xx */ +#define OMAP44XX_DMA_DSS_DISPC_REQ 6 /* S_DMA_5 */ +#define OMAP44XX_DMA_SYS_REQ2 7 /* S_DMA_6 */ +#define OMAP44XX_DMA_ISS_REQ1 9 /* S_DMA_8 */ +#define OMAP44XX_DMA_ISS_REQ2 10 /* S_DMA_9 */ +#define OMAP44XX_DMA_ISS_REQ3 12 /* S_DMA_11 */ +#define OMAP44XX_DMA_ISS_REQ4 13 /* S_DMA_12 */ +#define OMAP44XX_DMA_DSS_RFBI_REQ 14 /* S_DMA_13 */ +#define OMAP44XX_DMA_SPI3_TX0 15 /* S_DMA_14 */ +#define OMAP44XX_DMA_SPI3_RX0 16 /* S_DMA_15 */ +#define OMAP44XX_DMA_MCBSP2_TX 17 /* S_DMA_16 */ +#define OMAP44XX_DMA_MCBSP2_RX 18 /* S_DMA_17 */ +#define OMAP44XX_DMA_MCBSP3_TX 19 /* S_DMA_18 */ +#define OMAP44XX_DMA_MCBSP3_RX 20 /* S_DMA_19 */ +#define OMAP44XX_DMA_SPI3_TX1 23 /* S_DMA_22 */ +#define OMAP44XX_DMA_SPI3_RX1 24 /* S_DMA_23 */ +#define OMAP44XX_DMA_I2C3_TX 25 /* S_DMA_24 */ +#define OMAP44XX_DMA_I2C3_RX 26 /* S_DMA_25 */ +#define OMAP44XX_DMA_I2C1_TX 27 /* S_DMA_26 */ +#define OMAP44XX_DMA_I2C1_RX 28 /* S_DMA_27 */ +#define OMAP44XX_DMA_I2C2_TX 29 /* S_DMA_28 */ +#define OMAP44XX_DMA_I2C2_RX 30 /* S_DMA_29 */ +#define OMAP44XX_DMA_MCBSP4_TX 31 /* S_DMA_30 */ +#define OMAP44XX_DMA_MCBSP4_RX 32 /* S_DMA_31 */ +#define OMAP44XX_DMA_MCBSP1_TX 33 /* S_DMA_32 */ +#define OMAP44XX_DMA_MCBSP1_RX 34 /* S_DMA_33 */ +#define OMAP44XX_DMA_SPI1_TX0 35 /* S_DMA_34 */ +#define OMAP44XX_DMA_SPI1_RX0 36 /* S_DMA_35 */ +#define OMAP44XX_DMA_SPI1_TX1 37 /* S_DMA_36 */ +#define OMAP44XX_DMA_SPI1_RX1 38 /* S_DMA_37 */ +#define OMAP44XX_DMA_SPI1_TX2 39 /* S_DMA_38 */ +#define OMAP44XX_DMA_SPI1_RX2 40 /* S_DMA_39 */ +#define OMAP44XX_DMA_SPI1_TX3 41 /* S_DMA_40 */ +#define OMAP44XX_DMA_SPI1_RX3 42 /* S_DMA_41 */ +#define OMAP44XX_DMA_SPI2_TX0 43 /* S_DMA_42 */ +#define OMAP44XX_DMA_SPI2_RX0 44 /* S_DMA_43 */ +#define OMAP44XX_DMA_SPI2_TX1 45 /* S_DMA_44 */ +#define OMAP44XX_DMA_SPI2_RX1 46 /* S_DMA_45 */ +#define OMAP44XX_DMA_MMC2_TX 47 /* S_DMA_46 */ +#define OMAP44XX_DMA_MMC2_RX 48 /* S_DMA_47 */ +#define OMAP44XX_DMA_UART1_TX 49 /* S_DMA_48 */ +#define OMAP44XX_DMA_UART1_RX 50 /* S_DMA_49 */ +#define OMAP44XX_DMA_UART2_TX 51 /* S_DMA_50 */ +#define OMAP44XX_DMA_UART2_RX 52 /* S_DMA_51 */ +#define OMAP44XX_DMA_UART3_TX 53 /* S_DMA_52 */ +#define OMAP44XX_DMA_UART3_RX 54 /* S_DMA_53 */ +#define OMAP44XX_DMA_UART4_TX 55 /* S_DMA_54 */ +#define OMAP44XX_DMA_UART4_RX 56 /* S_DMA_55 */ +#define OMAP44XX_DMA_MMC4_TX 57 /* S_DMA_56 */ +#define OMAP44XX_DMA_MMC4_RX 58 /* S_DMA_57 */ +#define OMAP44XX_DMA_MMC5_TX 59 /* S_DMA_58 */ +#define OMAP44XX_DMA_MMC5_RX 60 /* S_DMA_59 */ +#define OMAP44XX_DMA_MMC1_TX 61 /* S_DMA_60 */ +#define OMAP44XX_DMA_MMC1_RX 62 /* S_DMA_61 */ +#define OMAP44XX_DMA_SYS_REQ3 64 /* S_DMA_63 */ +#define OMAP44XX_DMA_MCPDM_UP 65 /* S_DMA_64 */ +#define OMAP44XX_DMA_MCPDM_DL 66 /* S_DMA_65 */ +#define OMAP44XX_DMA_SPI4_TX0 70 /* S_DMA_69 */ +#define OMAP44XX_DMA_SPI4_RX0 71 /* S_DMA_70 */ +#define OMAP44XX_DMA_DSS_DSI1_REQ0 72 /* S_DMA_71 */ +#define OMAP44XX_DMA_DSS_DSI1_REQ1 73 /* S_DMA_72 */ +#define OMAP44XX_DMA_DSS_DSI1_REQ2 74 /* S_DMA_73 */ +#define OMAP44XX_DMA_DSS_DSI1_REQ3 75 /* S_DMA_74 */ +#define OMAP44XX_DMA_DSS_HDMI_REQ 76 /* S_DMA_75 */ +#define OMAP44XX_DMA_MMC3_TX 77 /* S_DMA_76 */ +#define OMAP44XX_DMA_MMC3_RX 78 /* S_DMA_77 */ +#define OMAP44XX_DMA_USIM_TX 79 /* S_DMA_78 */ +#define OMAP44XX_DMA_USIM_RX 80 /* S_DMA_79 */ +#define OMAP44XX_DMA_DSS_DSI2_REQ0 81 /* S_DMA_80 */ +#define OMAP44XX_DMA_DSS_DSI2_REQ1 82 /* S_DMA_81 */ +#define OMAP44XX_DMA_DSS_DSI2_REQ2 83 /* S_DMA_82 */ +#define OMAP44XX_DMA_DSS_DSI2_REQ3 84 /* S_DMA_83 */ +#define OMAP44XX_DMA_ABE_REQ0 101 /* S_DMA_100 */ +#define OMAP44XX_DMA_ABE_REQ1 102 /* S_DMA_101 */ +#define OMAP44XX_DMA_ABE_REQ2 103 /* S_DMA_102 */ +#define OMAP44XX_DMA_ABE_REQ3 104 /* S_DMA_103 */ +#define OMAP44XX_DMA_ABE_REQ4 105 /* S_DMA_104 */ +#define OMAP44XX_DMA_ABE_REQ5 106 /* S_DMA_105 */ +#define OMAP44XX_DMA_ABE_REQ6 107 /* S_DMA_106 */ +#define OMAP44XX_DMA_ABE_REQ7 108 /* S_DMA_107 */ +#define OMAP44XX_DMA_I2C4_TX 124 /* S_DMA_123 */ +#define OMAP44XX_DMA_I2C4_RX 125 /* S_DMA_124 */ + /*----------------------------------------------------------------------------*/ /* Hardware registers for LCD DMA */ diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index bb154ea76769..ec6f81e06d39 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -53,6 +53,11 @@ #define OMAP34XX_MCBSP4_BASE 0x49026000 #define OMAP34XX_MCBSP5_BASE 0x48096000 +#define OMAP44XX_MCBSP1_BASE 0x49022000 +#define OMAP44XX_MCBSP2_BASE 0x49024000 +#define OMAP44XX_MCBSP3_BASE 0x49026000 +#define OMAP44XX_MCBSP4_BASE 0x48074000 + #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) #define OMAP_MCBSP_REG_DRR2 0x00 @@ -98,7 +103,8 @@ #define AUDIO_DMA_TX OMAP_DMA_MCBSP1_TX #define AUDIO_DMA_RX OMAP_DMA_MCBSP1_RX -#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) #define OMAP_MCBSP_REG_DRR2 0x00 #define OMAP_MCBSP_REG_DRR1 0x04 diff --git a/arch/arm/plat-omap/include/mach/serial.h b/arch/arm/plat-omap/include/mach/serial.h index 13abd02d1527..def0529c75eb 100644 --- a/arch/arm/plat-omap/include/mach/serial.h +++ b/arch/arm/plat-omap/include/mach/serial.h @@ -59,6 +59,7 @@ extern void omap_uart_check_wakeup(void); extern void omap_uart_prepare_suspend(void); extern void omap_uart_prepare_idle(int num); extern void omap_uart_resume_idle(int num); +extern void omap_uart_enable_irqs(int enable); #endif #endif diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index efa0e0111f38..e42fa7cfc795 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -191,7 +191,7 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2); OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1); OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0); - if (cpu_is_omap2430() || cpu_is_omap34xx()) { + if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { OMAP_MCBSP_WRITE(io_base, XCCR, config->xccr); OMAP_MCBSP_WRITE(io_base, RCCR, config->rccr); } diff --git a/arch/arm/plat-pxa/gpio.c b/arch/arm/plat-pxa/gpio.c index abc79d44acaa..98548c6903a0 100644 --- a/arch/arm/plat-pxa/gpio.c +++ b/arch/arm/plat-pxa/gpio.c @@ -16,7 +16,7 @@ #include <linux/irq.h> #include <linux/io.h> #include <linux/sysdev.h> -#include <linux/bootmem.h> +#include <linux/slab.h> #include <mach/gpio.h> @@ -112,17 +112,12 @@ static int __init pxa_init_gpio_chip(int gpio_end) int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1; struct pxa_gpio_chip *chips; - /* this is early, we have to use bootmem allocator, and we really - * want this to be allocated dynamically for different 'gpio_end' - */ - chips = alloc_bootmem_low(nbanks * sizeof(struct pxa_gpio_chip)); + chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL); if (chips == NULL) { pr_err("%s: failed to allocate GPIO chips\n", __func__); return -ENOMEM; } - memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip)); - for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) { struct gpio_chip *c = &chips[i].chip; diff --git a/arch/arm/plat-s3c/Kconfig b/arch/arm/plat-s3c/Kconfig index 935c7558469b..8931c5f0e46b 100644 --- a/arch/arm/plat-s3c/Kconfig +++ b/arch/arm/plat-s3c/Kconfig @@ -198,4 +198,9 @@ config S3C_DEV_USB_HSOTG help Compile in platform device definition for USB high-speed OtG +config S3C_DEV_NAND + bool + help + Compile in platform device definition for NAND controller + endif diff --git a/arch/arm/plat-s3c/Makefile b/arch/arm/plat-s3c/Makefile index 0761766b1833..3c09109e9e84 100644 --- a/arch/arm/plat-s3c/Makefile +++ b/arch/arm/plat-s3c/Makefile @@ -28,13 +28,17 @@ obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += pm-gpio.o obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o +# PWM support + +obj-$(CONFIG_HAVE_PWM) += pwm.o + # devices obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o obj-y += dev-i2c0.o obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o -obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += dev-audio.o obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o +obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o diff --git a/arch/arm/plat-s3c/dev-nand.c b/arch/arm/plat-s3c/dev-nand.c new file mode 100644 index 000000000000..4e5323732434 --- /dev/null +++ b/arch/arm/plat-s3c/dev-nand.c @@ -0,0 +1,30 @@ +/* + * S3C series device definition for nand device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <mach/map.h> +#include <plat/devs.h> + +static struct resource s3c_nand_resource[] = { + [0] = { + .start = S3C_PA_NAND, + .end = S3C_PA_NAND + SZ_1M, + .flags = IORESOURCE_MEM, + } +}; + +struct platform_device s3c_device_nand = { + .name = "s3c2410-nand", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_nand_resource), + .resource = s3c_nand_resource, +}; + +EXPORT_SYMBOL(s3c_device_nand); diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h index d847bd476b6c..5f3b1cd53b90 100644 --- a/arch/arm/plat-s3c/include/plat/adc.h +++ b/arch/arm/plat-s3c/include/plat/adc.h @@ -19,10 +19,14 @@ struct s3c_adc_client; extern int s3c_adc_start(struct s3c_adc_client *client, unsigned int channel, unsigned int nr_samples); +extern int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch); + extern struct s3c_adc_client * s3c_adc_register(struct platform_device *pdev, - void (*select)(unsigned selected), - void (*conv)(unsigned d0, unsigned d1, + void (*select)(struct s3c_adc_client *client, + unsigned selected), + void (*conv)(struct s3c_adc_client *client, + unsigned d0, unsigned d1, unsigned *samples_left), unsigned int is_ts); diff --git a/arch/arm/plat-s3c/include/plat/cpu-freq.h b/arch/arm/plat-s3c/include/plat/cpu-freq.h index c86a13307e90..7b982b7f28cd 100644 --- a/arch/arm/plat-s3c/include/plat/cpu-freq.h +++ b/arch/arm/plat-s3c/include/plat/cpu-freq.h @@ -17,6 +17,21 @@ struct s3c_cpufreq_info; struct s3c_cpufreq_board; struct s3c_iotimings; +/** + * struct s3c_freq - frequency information (mainly for core drivers) + * @fclk: The FCLK frequency in Hz. + * @armclk: The ARMCLK frequency in Hz. + * @hclk_tns: HCLK cycle time in 10ths of nano-seconds. + * @hclk: The HCLK frequency in Hz. + * @pclk: The PCLK frequency in Hz. + * + * This contains the frequency information about the current configuration + * mainly for the core drivers to ensure we do not end up passing about + * a large number of parameters. + * + * The @hclk_tns field is a useful cache for the parts of the drivers that + * need to calculate IO timings and suchlike. + */ struct s3c_freq { unsigned long fclk; unsigned long armclk; @@ -25,48 +40,84 @@ struct s3c_freq { unsigned long pclk; }; -/* wrapper 'struct cpufreq_freqs' so that any drivers receiving the +/** + * struct s3c_cpufreq_freqs - s3c cpufreq notification information. + * @freqs: The cpufreq setting information. + * @old: The old clock settings. + * @new: The new clock settings. + * @pll_changing: Set if the PLL is changing. + * + * Wrapper 'struct cpufreq_freqs' so that any drivers receiving the * notification can use this information that is not provided by just * having the core frequency alone. + * + * The pll_changing flag is used to indicate if the PLL itself is + * being set during this change. This is important as the clocks + * will temporarily be set to the XTAL clock during this time, so + * drivers may want to close down their output during this time. + * + * Note, this is not being used by any current drivers and therefore + * may be removed in the future. */ - struct s3c_cpufreq_freqs { struct cpufreq_freqs freqs; struct s3c_freq old; struct s3c_freq new; + + unsigned int pll_changing:1; }; #define to_s3c_cpufreq(_cf) container_of(_cf, struct s3c_cpufreq_freqs, freqs) +/** + * struct s3c_clkdivs - clock divisor information + * @p_divisor: Divisor from FCLK to PCLK. + * @h_divisor: Divisor from FCLK to HCLK. + * @arm_divisor: Divisor from FCLK to ARMCLK (not all CPUs). + * @dvs: Non-zero if using DVS mode for ARMCLK. + * + * Divisor settings for the core clocks. + */ struct s3c_clkdivs { - int p_divisor; /* fclk / pclk */ - int h_divisor; /* fclk / hclk */ - int arm_divisor; /* not all cpus have this. */ - unsigned char dvs; /* using dvs mode to arm. */ + int p_divisor; + int h_divisor; + int arm_divisor; + unsigned char dvs; }; #define PLLVAL(_m, _p, _s) (((_m) << 12) | ((_p) << 4) | (_s)) +/** + * struct s3c_pllval - PLL value entry. + * @freq: The frequency for this entry in Hz. + * @pll_reg: The PLL register setting for this PLL value. + */ struct s3c_pllval { unsigned long freq; unsigned long pll_reg; }; -struct s3c_cpufreq_config { - struct s3c_freq freq; - struct s3c_pllval pll; - struct s3c_clkdivs divs; - struct s3c_cpufreq_info *info; /* for core, not drivers */ - struct s3c_cpufreq_board *board; -}; - -/* s3c_cpufreq_board +/** + * struct s3c_cpufreq_board - per-board cpu frequency informatin + * @refresh: The SDRAM refresh period in nanoseconds. + * @auto_io: Set if the IO timing settings should be generated from the + * initialisation time hardware registers. + * @need_io: Set if the board has external IO on any of the chipselect + * lines that will require the hardware timing registers to be + * updated on a clock change. + * @max: The maxium frequency limits for the system. Any field that + * is left at zero will use the CPU's settings. + * + * This contains the board specific settings that affect how the CPU + * drivers chose settings. These include the memory refresh and IO + * timing information. * - * per-board configuraton information, such as memory refresh and - * how to initialise IO timings. + * Registration depends on the driver being used, the ARMCLK only + * implementation does not currently need this but the older style + * driver requires this to be available. */ struct s3c_cpufreq_board { - unsigned int refresh; /* refresh period in ns */ + unsigned int refresh; unsigned int auto_io:1; /* automatically init io timings. */ unsigned int need_io:1; /* set if needs io timing support. */ diff --git a/arch/arm/plat-s3c/include/plat/cpu.h b/arch/arm/plat-s3c/include/plat/cpu.h index be541cbba070..fbc3d498e02e 100644 --- a/arch/arm/plat-s3c/include/plat/cpu.h +++ b/arch/arm/plat-s3c/include/plat/cpu.h @@ -65,6 +65,7 @@ extern struct sys_timer s3c24xx_timer; /* system device classes */ extern struct sysdev_class s3c2410_sysclass; +extern struct sysdev_class s3c2410a_sysclass; extern struct sysdev_class s3c2412_sysclass; extern struct sysdev_class s3c2440_sysclass; extern struct sysdev_class s3c2442_sysclass; diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h index 2e170827e0b0..0f540ea1e999 100644 --- a/arch/arm/plat-s3c/include/plat/devs.h +++ b/arch/arm/plat-s3c/include/plat/devs.h @@ -46,6 +46,8 @@ extern struct platform_device s3c_device_hsmmc2; extern struct platform_device s3c_device_spi0; extern struct platform_device s3c_device_spi1; +extern struct platform_device s3c_device_hwmon; + extern struct platform_device s3c_device_nand; extern struct platform_device s3c_device_usbgadget; @@ -56,5 +58,6 @@ extern struct platform_device s3c_device_usb_hsotg; #ifdef CONFIG_CPU_S3C2440 extern struct platform_device s3c_device_camif; +extern struct platform_device s3c_device_ac97; #endif diff --git a/arch/arm/plat-s3c/include/plat/hwmon.h b/arch/arm/plat-s3c/include/plat/hwmon.h new file mode 100644 index 000000000000..1ba88ea0aa31 --- /dev/null +++ b/arch/arm/plat-s3c/include/plat/hwmon.h @@ -0,0 +1,41 @@ +/* linux/arch/arm/plat-s3c/include/plat/hwmon.h + * + * Copyright 2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * S3C - HWMon interface for ADC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_ADC_HWMON_H +#define __ASM_ARCH_ADC_HWMON_H __FILE__ + +/** + * s3c_hwmon_chcfg - channel configuration + * @name: The name to give this channel. + * @mult: Multiply the ADC value read by this. + * @div: Divide the value from the ADC by this. + * + * The value read from the ADC is converted to a value that + * hwmon expects (mV) by result = (value_read * @mult) / @div. + */ +struct s3c_hwmon_chcfg { + const char *name; + unsigned int mult; + unsigned int div; +}; + +/** + * s3c_hwmon_pdata - HWMON platform data + * @in: One configuration for each possible channel used. + */ +struct s3c_hwmon_pdata { + struct s3c_hwmon_chcfg *in[8]; +}; + +#endif /* __ASM_ARCH_ADC_HWMON_H */ + diff --git a/arch/arm/plat-s3c/include/plat/map-base.h b/arch/arm/plat-s3c/include/plat/map-base.h index b84289d32a54..250be311c85b 100644 --- a/arch/arm/plat-s3c/include/plat/map-base.h +++ b/arch/arm/plat-s3c/include/plat/map-base.h @@ -32,9 +32,15 @@ #define S3C_VA_IRQ S3C_ADDR(0x00000000) /* irq controller(s) */ #define S3C_VA_SYS S3C_ADDR(0x00100000) /* system control */ -#define S3C_VA_MEM S3C_ADDR(0x00200000) /* system control */ +#define S3C_VA_MEM S3C_ADDR(0x00200000) /* memory control */ #define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */ #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */ #define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */ +/* This is used for the CPU specific mappings that may be needed, so that + * they do not need to directly used S3C_ADDR() and thus make it easier to + * modify the space for mapping. + */ +#define S3C_ADDR_CPU(x) S3C_ADDR(0x00500000 + (x)) + #endif /* __ASM_PLAT_MAP_H */ diff --git a/arch/arm/plat-s3c24xx/pwm.c b/arch/arm/plat-s3c/pwm.c index 0120b760315b..f3d37ac5595b 100644 --- a/arch/arm/plat-s3c24xx/pwm.c +++ b/arch/arm/plat-s3c/pwm.c @@ -1,10 +1,10 @@ -/* arch/arm/plat-s3c24xx/pwm.c +/* arch/arm/plat-s3c/pwm.c * * Copyright (c) 2007 Ben Dooks * Copyright (c) 2008 Simtec Electronics * Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org> * - * S3C24XX PWM device core + * S3C series PWM device core * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include <linux/pwm.h> #include <mach/irqs.h> +#include <mach/map.h> #include <plat/devs.h> #include <plat/regs-timer.h> diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 5b0bc914f58e..9c7aca489643 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -10,6 +10,7 @@ config PLAT_S3C24XX default y select NO_IOPORT select ARCH_REQUIRE_GPIOLIB + select S3C_DEVICE_NAND help Base platform code for any Samsung S3C24XX device @@ -34,6 +35,40 @@ config CPU_S3C244X help Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems. +config S3C2440_CPUFREQ + bool "S3C2440/S3C2442 CPU Frequency scaling support" + depends on CPU_FREQ_S3C24XX && (CPU_S3C2440 || CPU_S3C2442) + select S3C2410_CPUFREQ_UTILS + default y + help + CPU Frequency scaling support for S3C2440 and S3C2442 SoC CPUs. + +config S3C2440_XTAL_12000000 + bool + help + Indicate that the build needs to support 12MHz system + crystal. + +config S3C2440_XTAL_16934400 + bool + help + Indicate that the build needs to support 16.9344MHz system + crystal. + +config S3C2440_PLL_12000000 + bool + depends on S3C2440_CPUFREQ && S3C2440_XTAL_12000000 + default y if CPU_FREQ_S3C24XX_PLL + help + PLL tables for S3C2440 or S3C2442 CPUs with 12MHz crystals. + +config S3C2440_PLL_16934400 + bool + depends on S3C2440_CPUFREQ && S3C2440_XTAL_16934400 + default y if CPU_FREQ_S3C24XX_PLL + help + PLL tables for S3C2440 or S3C2442 CPUs with 16.934MHz crystals. + config S3C24XX_PWM bool "PWM device support" select HAVE_PWM @@ -105,8 +140,39 @@ config S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7 SPI GPIO configuration code for BUS 1 when connected to GPG5, GPG6 and GPG7. +config S3C24XX_SPI_BUS1_GPD8_GPD9_GPD10 + bool + help + SPI GPIO configuration code for BUS 1 when connected to + GPD8, GPD9 and GPD10. + # common code for s3c24xx based machines, such as the SMDKs. +# cpu frequency items common between s3c2410 and s3c2440/s3c2442 + +config S3C2410_IOTIMING + bool + depends on CPU_FREQ_S3C24XX + help + Internal node to select io timing code that is common to the s3c2410 + and s3c2440/s3c2442 cpu frequency support. + +config S3C2410_CPUFREQ_UTILS + bool + depends on CPU_FREQ_S3C24XX + help + Internal node to select timing code that is common to the s3c2410 + and s3c2440/s3c244 cpu frequency support. + +# cpu frequency support common to s3c2412, s3c2413 and s3c2442 + +config S3C2412_IOTIMING + bool + depends on CPU_FREQ_S3C24XX && (CPU_S3C2412 || CPU_S3C2443) + help + Intel node to select io timing code that is common to the s3c2412 + and the s3c2443. + config MACH_SMDK bool help diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index 579a165c2827..7780d2dd833a 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile @@ -20,19 +20,28 @@ obj-y += gpiolib.o obj-y += clock.o obj-$(CONFIG_S3C24XX_DCLK) += clock-dclk.o +obj-$(CONFIG_CPU_FREQ_S3C24XX) += cpu-freq.o +obj-$(CONFIG_CPU_FREQ_S3C24XX_DEBUGFS) += cpu-freq-debugfs.o + # Architecture dependant builds obj-$(CONFIG_CPU_S3C244X) += s3c244x.o obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o obj-$(CONFIG_CPU_S3C244X) += s3c244x-clock.o +obj-$(CONFIG_S3C2440_CPUFREQ) += s3c2440-cpufreq.o +obj-$(CONFIG_S3C2440_PLL_12000000) += s3c2440-pll-12000000.o +obj-$(CONFIG_S3C2440_PLL_16934400) += s3c2440-pll-16934400.o + obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += irq-pm.o obj-$(CONFIG_PM) += sleep.o -obj-$(CONFIG_S3C24XX_PWM) += pwm.o obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o obj-$(CONFIG_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C24XX_ADC) += adc.o +obj-$(CONFIG_S3C2410_IOTIMING) += s3c2410-iotiming.o +obj-$(CONFIG_S3C2412_IOTIMING) += s3c2412-iotiming.o +obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += s3c2410-cpufreq-utils.o # device specific setup and/or initialisation obj-$(CONFIG_ARCH_S3C2410) += setup-i2c.o @@ -41,6 +50,7 @@ obj-$(CONFIG_ARCH_S3C2410) += setup-i2c.o obj-$(CONFIG_S3C24XX_SPI_BUS0_GPE11_GPE12_GPE13) += spi-bus0-gpe11_12_13.o obj-$(CONFIG_S3C24XX_SPI_BUS1_GPG5_GPG6_GPG7) += spi-bus1-gpg5_6_7.o +obj-$(CONFIG_S3C24XX_SPI_BUS1_GPD8_GPD9_GPD10) += spi-bus1-gpd8_9_10.o # machine common support diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c index ee1baf11ad9e..11117a7ba911 100644 --- a/arch/arm/plat-s3c24xx/adc.c +++ b/arch/arm/plat-s3c24xx/adc.c @@ -39,13 +39,16 @@ struct s3c_adc_client { struct platform_device *pdev; struct list_head pend; + wait_queue_head_t *wait; unsigned int nr_samples; + int result; unsigned char is_ts; unsigned char channel; - void (*select_cb)(unsigned selected); - void (*convert_cb)(unsigned val1, unsigned val2, + void (*select_cb)(struct s3c_adc_client *c, unsigned selected); + void (*convert_cb)(struct s3c_adc_client *c, + unsigned val1, unsigned val2, unsigned *samples_left); }; @@ -81,7 +84,7 @@ static inline void s3c_adc_select(struct adc_device *adc, { unsigned con = readl(adc->regs + S3C2410_ADCCON); - client->select_cb(1); + client->select_cb(client, 1); con &= ~S3C2410_ADCCON_MUXMASK; con &= ~S3C2410_ADCCON_STDBM; @@ -153,25 +156,61 @@ int s3c_adc_start(struct s3c_adc_client *client, } EXPORT_SYMBOL_GPL(s3c_adc_start); -static void s3c_adc_default_select(unsigned select) +static void s3c_convert_done(struct s3c_adc_client *client, + unsigned v, unsigned u, unsigned *left) +{ + client->result = v; + wake_up(client->wait); +} + +int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch) +{ + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake); + int ret; + + client->convert_cb = s3c_convert_done; + client->wait = &wake; + client->result = -1; + + ret = s3c_adc_start(client, ch, 1); + if (ret < 0) + goto err; + + ret = wait_event_timeout(wake, client->result >= 0, HZ / 2); + if (client->result < 0) { + ret = -ETIMEDOUT; + goto err; + } + + client->convert_cb = NULL; + return client->result; + +err: + return ret; +} +EXPORT_SYMBOL_GPL(s3c_adc_convert); + +static void s3c_adc_default_select(struct s3c_adc_client *client, + unsigned select) { } struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, - void (*select)(unsigned int selected), - void (*conv)(unsigned d0, unsigned d1, + void (*select)(struct s3c_adc_client *client, + unsigned int selected), + void (*conv)(struct s3c_adc_client *client, + unsigned d0, unsigned d1, unsigned *samples_left), unsigned int is_ts) { struct s3c_adc_client *client; WARN_ON(!pdev); - WARN_ON(!conv); if (!select) select = s3c_adc_default_select; - if (!conv || !pdev) + if (!pdev) return ERR_PTR(-EINVAL); client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL); @@ -230,16 +269,19 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw) adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); client->nr_samples--; - (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff, &client->nr_samples); + + if (client->convert_cb) + (client->convert_cb)(client, data0 & 0x3ff, data1 & 0x3ff, + &client->nr_samples); if (client->nr_samples > 0) { /* fire another conversion for this */ - client->select_cb(1); + client->select_cb(client, 1); s3c_adc_convert(adc); } else { local_irq_save(flags); - (client->select_cb)(0); + (client->select_cb)(client, 0); adc->cur = NULL; s3c_adc_try(adc); diff --git a/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c b/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c new file mode 100644 index 000000000000..a9276667c2fb --- /dev/null +++ b/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c @@ -0,0 +1,199 @@ +/* linux/arch/arm/plat-s3c24xx/cpu-freq-debugfs.c + * + * Copyright (c) 2009 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX CPU Frequency scaling - debugfs status support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/err.h> + +#include <plat/cpu-freq-core.h> + +static struct dentry *dbgfs_root; +static struct dentry *dbgfs_file_io; +static struct dentry *dbgfs_file_info; +static struct dentry *dbgfs_file_board; + +#define print_ns(x) ((x) / 10), ((x) % 10) + +static void show_max(struct seq_file *seq, struct s3c_freq *f) +{ + seq_printf(seq, "MAX: F=%lu, H=%lu, P=%lu, A=%lu\n", + f->fclk, f->hclk, f->pclk, f->armclk); +} + +static int board_show(struct seq_file *seq, void *p) +{ + struct s3c_cpufreq_config *cfg; + struct s3c_cpufreq_board *brd; + + cfg = s3c_cpufreq_getconfig(); + if (!cfg) { + seq_printf(seq, "no configuration registered\n"); + return 0; + } + + brd = cfg->board; + if (!brd) { + seq_printf(seq, "no board definition set?\n"); + return 0; + } + + seq_printf(seq, "SDRAM refresh %u ns\n", brd->refresh); + seq_printf(seq, "auto_io=%u\n", brd->auto_io); + seq_printf(seq, "need_io=%u\n", brd->need_io); + + show_max(seq, &brd->max); + + + return 0; +} + +static int fops_board_open(struct inode *inode, struct file *file) +{ + return single_open(file, board_show, NULL); +} + +static const struct file_operations fops_board = { + .open = fops_board_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int info_show(struct seq_file *seq, void *p) +{ + struct s3c_cpufreq_config *cfg; + + cfg = s3c_cpufreq_getconfig(); + if (!cfg) { + seq_printf(seq, "no configuration registered\n"); + return 0; + } + + seq_printf(seq, " FCLK %ld Hz\n", cfg->freq.fclk); + seq_printf(seq, " HCLK %ld Hz (%lu.%lu ns)\n", + cfg->freq.hclk, print_ns(cfg->freq.hclk_tns)); + seq_printf(seq, " PCLK %ld Hz\n", cfg->freq.hclk); + seq_printf(seq, "ARMCLK %ld Hz\n", cfg->freq.armclk); + seq_printf(seq, "\n"); + + show_max(seq, &cfg->max); + + seq_printf(seq, "Divisors: P=%d, H=%d, A=%d, dvs=%s\n", + cfg->divs.h_divisor, cfg->divs.p_divisor, + cfg->divs.arm_divisor, cfg->divs.dvs ? "on" : "off"); + seq_printf(seq, "\n"); + + seq_printf(seq, "lock_pll=%u\n", cfg->lock_pll); + + return 0; +} + +static int fops_info_open(struct inode *inode, struct file *file) +{ + return single_open(file, info_show, NULL); +} + +static const struct file_operations fops_info = { + .open = fops_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int io_show(struct seq_file *seq, void *p) +{ + void (*show_bank)(struct seq_file *, struct s3c_cpufreq_config *, union s3c_iobank *); + struct s3c_cpufreq_config *cfg; + struct s3c_iotimings *iot; + union s3c_iobank *iob; + int bank; + + cfg = s3c_cpufreq_getconfig(); + if (!cfg) { + seq_printf(seq, "no configuration registered\n"); + return 0; + } + + show_bank = cfg->info->debug_io_show; + if (!show_bank) { + seq_printf(seq, "no code to show bank timing\n"); + return 0; + } + + iot = s3c_cpufreq_getiotimings(); + if (!iot) { + seq_printf(seq, "no io timings registered\n"); + return 0; + } + + seq_printf(seq, "hclk period is %lu.%lu ns\n", print_ns(cfg->freq.hclk_tns)); + + for (bank = 0; bank < MAX_BANKS; bank++) { + iob = &iot->bank[bank]; + + seq_printf(seq, "bank %d: ", bank); + + if (!iob->io_2410) { + seq_printf(seq, "nothing set\n"); + continue; + } + + show_bank(seq, cfg, iob); + } + + return 0; +} + +static int fops_io_open(struct inode *inode, struct file *file) +{ + return single_open(file, io_show, NULL); +} + +static const struct file_operations fops_io = { + .open = fops_io_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + + +static int __init s3c_freq_debugfs_init(void) +{ + dbgfs_root = debugfs_create_dir("s3c-cpufreq", NULL); + if (IS_ERR(dbgfs_root)) { + printk(KERN_ERR "%s: error creating debugfs root\n", __func__); + return PTR_ERR(dbgfs_root); + } + + dbgfs_file_io = debugfs_create_file("io-timing", S_IRUGO, dbgfs_root, + NULL, &fops_io); + + dbgfs_file_info = debugfs_create_file("info", S_IRUGO, dbgfs_root, + NULL, &fops_info); + + dbgfs_file_board = debugfs_create_file("board", S_IRUGO, dbgfs_root, + NULL, &fops_board); + + return 0; +} + +late_initcall(s3c_freq_debugfs_init); + diff --git a/arch/arm/plat-s3c24xx/cpu-freq.c b/arch/arm/plat-s3c24xx/cpu-freq.c new file mode 100644 index 000000000000..4f1b789a1173 --- /dev/null +++ b/arch/arm/plat-s3c24xx/cpu-freq.c @@ -0,0 +1,716 @@ +/* linux/arch/arm/plat-s3c24xx/cpu-freq.c + * + * Copyright (c) 2006,2007,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX CPU Frequency scaling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/cpu.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/sysdev.h> +#include <linux/kobject.h> +#include <linux/sysfs.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <plat/cpu.h> +#include <plat/clock.h> +#include <plat/cpu-freq-core.h> + +#include <mach/regs-clock.h> + +/* note, cpufreq support deals in kHz, no Hz */ + +static struct cpufreq_driver s3c24xx_driver; +static struct s3c_cpufreq_config cpu_cur; +static struct s3c_iotimings s3c24xx_iotiming; +static struct cpufreq_frequency_table *pll_reg; +static unsigned int last_target = ~0; +static unsigned int ftab_size; +static struct cpufreq_frequency_table *ftab; + +static struct clk *_clk_mpll; +static struct clk *_clk_xtal; +static struct clk *clk_fclk; +static struct clk *clk_hclk; +static struct clk *clk_pclk; +static struct clk *clk_arm; + +#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS +struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void) +{ + return &cpu_cur; +} + +struct s3c_iotimings *s3c_cpufreq_getiotimings(void) +{ + return &s3c24xx_iotiming; +} +#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUGFS */ + +static void s3c_cpufreq_getcur(struct s3c_cpufreq_config *cfg) +{ + unsigned long fclk, pclk, hclk, armclk; + + cfg->freq.fclk = fclk = clk_get_rate(clk_fclk); + cfg->freq.hclk = hclk = clk_get_rate(clk_hclk); + cfg->freq.pclk = pclk = clk_get_rate(clk_pclk); + cfg->freq.armclk = armclk = clk_get_rate(clk_arm); + + cfg->pll.index = __raw_readl(S3C2410_MPLLCON); + cfg->pll.frequency = fclk; + + cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10); + + cfg->divs.h_divisor = fclk / hclk; + cfg->divs.p_divisor = fclk / pclk; +} + +static inline void s3c_cpufreq_calc(struct s3c_cpufreq_config *cfg) +{ + unsigned long pll = cfg->pll.frequency; + + cfg->freq.fclk = pll; + cfg->freq.hclk = pll / cfg->divs.h_divisor; + cfg->freq.pclk = pll / cfg->divs.p_divisor; + + /* convert hclk into 10ths of nanoseconds for io calcs */ + cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10); +} + +static inline int closer(unsigned int target, unsigned int n, unsigned int c) +{ + int diff_cur = abs(target - c); + int diff_new = abs(target - n); + + return (diff_new < diff_cur); +} + +static void s3c_cpufreq_show(const char *pfx, + struct s3c_cpufreq_config *cfg) +{ + s3c_freq_dbg("%s: Fvco=%u, F=%lu, A=%lu, H=%lu (%u), P=%lu (%u)\n", + pfx, cfg->pll.frequency, cfg->freq.fclk, cfg->freq.armclk, + cfg->freq.hclk, cfg->divs.h_divisor, + cfg->freq.pclk, cfg->divs.p_divisor); +} + +/* functions to wrapper the driver info calls to do the cpu specific work */ + +static void s3c_cpufreq_setio(struct s3c_cpufreq_config *cfg) +{ + if (cfg->info->set_iotiming) + (cfg->info->set_iotiming)(cfg, &s3c24xx_iotiming); +} + +static int s3c_cpufreq_calcio(struct s3c_cpufreq_config *cfg) +{ + if (cfg->info->calc_iotiming) + return (cfg->info->calc_iotiming)(cfg, &s3c24xx_iotiming); + + return 0; +} + +static void s3c_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) +{ + (cfg->info->set_refresh)(cfg); +} + +static void s3c_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) +{ + (cfg->info->set_divs)(cfg); +} + +static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) +{ + return (cfg->info->calc_divs)(cfg); +} + +static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg) +{ + (cfg->info->set_fvco)(cfg); +} + +static inline void s3c_cpufreq_resume_clocks(void) +{ + cpu_cur.info->resume_clocks(); +} + +static inline void s3c_cpufreq_updateclk(struct clk *clk, + unsigned int freq) +{ + clk_set_rate(clk, freq); +} + +static int s3c_cpufreq_settarget(struct cpufreq_policy *policy, + unsigned int target_freq, + struct cpufreq_frequency_table *pll) +{ + struct s3c_cpufreq_freqs freqs; + struct s3c_cpufreq_config cpu_new; + unsigned long flags; + + cpu_new = cpu_cur; /* copy new from current */ + + s3c_cpufreq_show("cur", &cpu_cur); + + /* TODO - check for DMA currently outstanding */ + + cpu_new.pll = pll ? *pll : cpu_cur.pll; + + if (pll) + freqs.pll_changing = 1; + + /* update our frequencies */ + + cpu_new.freq.armclk = target_freq; + cpu_new.freq.fclk = cpu_new.pll.frequency; + + if (s3c_cpufreq_calcdivs(&cpu_new) < 0) { + printk(KERN_ERR "no divisors for %d\n", target_freq); + goto err_notpossible; + } + + s3c_freq_dbg("%s: got divs\n", __func__); + + s3c_cpufreq_calc(&cpu_new); + + s3c_freq_dbg("%s: calculated frequencies for new\n", __func__); + + if (cpu_new.freq.hclk != cpu_cur.freq.hclk) { + if (s3c_cpufreq_calcio(&cpu_new) < 0) { + printk(KERN_ERR "%s: no IO timings\n", __func__); + goto err_notpossible; + } + } + + s3c_cpufreq_show("new", &cpu_new); + + /* setup our cpufreq parameters */ + + freqs.old = cpu_cur.freq; + freqs.new = cpu_new.freq; + + freqs.freqs.cpu = 0; + freqs.freqs.old = cpu_cur.freq.armclk / 1000; + freqs.freqs.new = cpu_new.freq.armclk / 1000; + + /* update f/h/p clock settings before we issue the change + * notification, so that drivers do not need to do anything + * special if they want to recalculate on CPUFREQ_PRECHANGE. */ + + s3c_cpufreq_updateclk(_clk_mpll, cpu_new.pll.frequency); + s3c_cpufreq_updateclk(clk_fclk, cpu_new.freq.fclk); + s3c_cpufreq_updateclk(clk_hclk, cpu_new.freq.hclk); + s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk); + + /* start the frequency change */ + + if (policy) + cpufreq_notify_transition(&freqs.freqs, CPUFREQ_PRECHANGE); + + /* If hclk is staying the same, then we do not need to + * re-write the IO or the refresh timings whilst we are changing + * speed. */ + + local_irq_save(flags); + + /* is our memory clock slowing down? */ + if (cpu_new.freq.hclk < cpu_cur.freq.hclk) { + s3c_cpufreq_setrefresh(&cpu_new); + s3c_cpufreq_setio(&cpu_new); + } + + if (cpu_new.freq.fclk == cpu_cur.freq.fclk) { + /* not changing PLL, just set the divisors */ + + s3c_cpufreq_setdivs(&cpu_new); + } else { + if (cpu_new.freq.fclk < cpu_cur.freq.fclk) { + /* slow the cpu down, then set divisors */ + + s3c_cpufreq_setfvco(&cpu_new); + s3c_cpufreq_setdivs(&cpu_new); + } else { + /* set the divisors, then speed up */ + + s3c_cpufreq_setdivs(&cpu_new); + s3c_cpufreq_setfvco(&cpu_new); + } + } + + /* did our memory clock speed up */ + if (cpu_new.freq.hclk > cpu_cur.freq.hclk) { + s3c_cpufreq_setrefresh(&cpu_new); + s3c_cpufreq_setio(&cpu_new); + } + + /* update our current settings */ + cpu_cur = cpu_new; + + local_irq_restore(flags); + + /* notify everyone we've done this */ + if (policy) + cpufreq_notify_transition(&freqs.freqs, CPUFREQ_POSTCHANGE); + + s3c_freq_dbg("%s: finished\n", __func__); + return 0; + + err_notpossible: + printk(KERN_ERR "no compatible settings for %d\n", target_freq); + return -EINVAL; +} + +/* s3c_cpufreq_target + * + * called by the cpufreq core to adjust the frequency that the CPU + * is currently running at. + */ + +static int s3c_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_frequency_table *pll; + unsigned int index; + + /* avoid repeated calls which cause a needless amout of duplicated + * logging output (and CPU time as the calculation process is + * done) */ + if (target_freq == last_target) + return 0; + + last_target = target_freq; + + s3c_freq_dbg("%s: policy %p, target %u, relation %u\n", + __func__, policy, target_freq, relation); + + if (ftab) { + if (cpufreq_frequency_table_target(policy, ftab, + target_freq, relation, + &index)) { + s3c_freq_dbg("%s: table failed\n", __func__); + return -EINVAL; + } + + s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__, + target_freq, index, ftab[index].frequency); + target_freq = ftab[index].frequency; + } + + target_freq *= 1000; /* convert target to Hz */ + + /* find the settings for our new frequency */ + + if (!pll_reg || cpu_cur.lock_pll) { + /* either we've not got any PLL values, or we've locked + * to the current one. */ + pll = NULL; + } else { + struct cpufreq_policy tmp_policy; + int ret; + + /* we keep the cpu pll table in Hz, to ensure we get an + * accurate value for the PLL output. */ + + tmp_policy.min = policy->min * 1000; + tmp_policy.max = policy->max * 1000; + tmp_policy.cpu = policy->cpu; + + /* cpufreq_frequency_table_target uses a pointer to 'index' + * which is the number of the table entry, not the value of + * the table entry's index field. */ + + ret = cpufreq_frequency_table_target(&tmp_policy, pll_reg, + target_freq, relation, + &index); + + if (ret < 0) { + printk(KERN_ERR "%s: no PLL available\n", __func__); + goto err_notpossible; + } + + pll = pll_reg + index; + + s3c_freq_dbg("%s: target %u => %u\n", + __func__, target_freq, pll->frequency); + + target_freq = pll->frequency; + } + + return s3c_cpufreq_settarget(policy, target_freq, pll); + + err_notpossible: + printk(KERN_ERR "no compatible settings for %d\n", target_freq); + return -EINVAL; +} + +static unsigned int s3c_cpufreq_get(unsigned int cpu) +{ + return clk_get_rate(clk_arm) / 1000; +} + +struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) +{ + struct clk *clk; + + clk = clk_get(dev, name); + if (IS_ERR(clk)) + printk(KERN_ERR "cpufreq: failed to get clock '%s'\n", name); + + return clk; +} + +static int s3c_cpufreq_init(struct cpufreq_policy *policy) +{ + printk(KERN_INFO "%s: initialising policy %p\n", __func__, policy); + + if (policy->cpu != 0) + return -EINVAL; + + policy->cur = s3c_cpufreq_get(0); + policy->min = policy->cpuinfo.min_freq = 0; + policy->max = policy->cpuinfo.max_freq = cpu_cur.info->max.fclk / 1000; + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + /* feed the latency information from the cpu driver */ + policy->cpuinfo.transition_latency = cpu_cur.info->latency; + + if (ftab) + cpufreq_frequency_table_cpuinfo(policy, ftab); + + return 0; +} + +static __init int s3c_cpufreq_initclks(void) +{ + _clk_mpll = s3c_cpufreq_clk_get(NULL, "mpll"); + _clk_xtal = s3c_cpufreq_clk_get(NULL, "xtal"); + clk_fclk = s3c_cpufreq_clk_get(NULL, "fclk"); + clk_hclk = s3c_cpufreq_clk_get(NULL, "hclk"); + clk_pclk = s3c_cpufreq_clk_get(NULL, "pclk"); + clk_arm = s3c_cpufreq_clk_get(NULL, "armclk"); + + if (IS_ERR(clk_fclk) || IS_ERR(clk_hclk) || IS_ERR(clk_pclk) || + IS_ERR(_clk_mpll) || IS_ERR(clk_arm) || IS_ERR(_clk_xtal)) { + printk(KERN_ERR "%s: could not get clock(s)\n", __func__); + return -ENOENT; + } + + printk(KERN_INFO "%s: clocks f=%lu,h=%lu,p=%lu,a=%lu\n", __func__, + clk_get_rate(clk_fclk) / 1000, + clk_get_rate(clk_hclk) / 1000, + clk_get_rate(clk_pclk) / 1000, + clk_get_rate(clk_arm) / 1000); + + return 0; +} + +static int s3c_cpufreq_verify(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + + return 0; +} + +#ifdef CONFIG_PM +static struct cpufreq_frequency_table suspend_pll; +static unsigned int suspend_freq; + +static int s3c_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg) +{ + suspend_pll.frequency = clk_get_rate(_clk_mpll); + suspend_pll.index = __raw_readl(S3C2410_MPLLCON); + suspend_freq = s3c_cpufreq_get(0) * 1000; + + return 0; +} + +static int s3c_cpufreq_resume(struct cpufreq_policy *policy) +{ + int ret; + + s3c_freq_dbg("%s: resuming with policy %p\n", __func__, policy); + + last_target = ~0; /* invalidate last_target setting */ + + /* first, find out what speed we resumed at. */ + s3c_cpufreq_resume_clocks(); + + /* whilst we will be called later on, we try and re-set the + * cpu frequencies as soon as possible so that we do not end + * up resuming devices and then immediatley having to re-set + * a number of settings once these devices have restarted. + * + * as a note, it is expected devices are not used until they + * have been un-suspended and at that time they should have + * used the updated clock settings. + */ + + ret = s3c_cpufreq_settarget(NULL, suspend_freq, &suspend_pll); + if (ret) { + printk(KERN_ERR "%s: failed to reset pll/freq\n", __func__); + return ret; + } + + return 0; +} +#else +#define s3c_cpufreq_resume NULL +#define s3c_cpufreq_suspend NULL +#endif + +static struct cpufreq_driver s3c24xx_driver = { + .flags = CPUFREQ_STICKY, + .verify = s3c_cpufreq_verify, + .target = s3c_cpufreq_target, + .get = s3c_cpufreq_get, + .init = s3c_cpufreq_init, + .suspend = s3c_cpufreq_suspend, + .resume = s3c_cpufreq_resume, + .name = "s3c24xx", +}; + + +int __init s3c_cpufreq_register(struct s3c_cpufreq_info *info) +{ + if (!info || !info->name) { + printk(KERN_ERR "%s: failed to pass valid information\n", + __func__); + return -EINVAL; + } + + printk(KERN_INFO "S3C24XX CPU Frequency driver, %s cpu support\n", + info->name); + + /* check our driver info has valid data */ + + BUG_ON(info->set_refresh == NULL); + BUG_ON(info->set_divs == NULL); + BUG_ON(info->calc_divs == NULL); + + /* info->set_fvco is optional, depending on whether there + * is a need to set the clock code. */ + + cpu_cur.info = info; + + /* Note, driver registering should probably update locktime */ + + return 0; +} + +int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) +{ + struct s3c_cpufreq_board *ours; + + if (!board) { + printk(KERN_INFO "%s: no board data\n", __func__); + return -EINVAL; + } + + /* Copy the board information so that each board can make this + * initdata. */ + + ours = kzalloc(sizeof(struct s3c_cpufreq_board), GFP_KERNEL); + if (ours == NULL) { + printk(KERN_ERR "%s: no memory\n", __func__); + return -ENOMEM; + } + + *ours = *board; + cpu_cur.board = ours; + + return 0; +} + +int __init s3c_cpufreq_auto_io(void) +{ + int ret; + + if (!cpu_cur.info->get_iotiming) { + printk(KERN_ERR "%s: get_iotiming undefined\n", __func__); + return -ENOENT; + } + + printk(KERN_INFO "%s: working out IO settings\n", __func__); + + ret = (cpu_cur.info->get_iotiming)(&cpu_cur, &s3c24xx_iotiming); + if (ret) + printk(KERN_ERR "%s: failed to get timings\n", __func__); + + return ret; +} + +/* if one or is zero, then return the other, otherwise return the min */ +#define do_min(_a, _b) ((_a) == 0 ? (_b) : (_b) == 0 ? (_a) : min(_a, _b)) + +/** + * s3c_cpufreq_freq_min - find the minimum settings for the given freq. + * @dst: The destination structure + * @a: One argument. + * @b: The other argument. + * + * Create a minimum of each frequency entry in the 'struct s3c_freq', + * unless the entry is zero when it is ignored and the non-zero argument + * used. + */ +static void s3c_cpufreq_freq_min(struct s3c_freq *dst, + struct s3c_freq *a, struct s3c_freq *b) +{ + dst->fclk = do_min(a->fclk, b->fclk); + dst->hclk = do_min(a->hclk, b->hclk); + dst->pclk = do_min(a->pclk, b->pclk); + dst->armclk = do_min(a->armclk, b->armclk); +} + +static inline u32 calc_locktime(u32 freq, u32 time_us) +{ + u32 result; + + result = freq * time_us; + result = DIV_ROUND_UP(result, 1000 * 1000); + + return result; +} + +static void s3c_cpufreq_update_loctkime(void) +{ + unsigned int bits = cpu_cur.info->locktime_bits; + u32 rate = (u32)clk_get_rate(_clk_xtal); + u32 val; + + if (bits == 0) { + WARN_ON(1); + return; + } + + val = calc_locktime(rate, cpu_cur.info->locktime_u) << bits; + val |= calc_locktime(rate, cpu_cur.info->locktime_m); + + printk(KERN_INFO "%s: new locktime is 0x%08x\n", __func__, val); + __raw_writel(val, S3C2410_LOCKTIME); +} + +static int s3c_cpufreq_build_freq(void) +{ + int size, ret; + + if (!cpu_cur.info->calc_freqtable) + return -EINVAL; + + kfree(ftab); + ftab = NULL; + + size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0); + size++; + + ftab = kmalloc(sizeof(struct cpufreq_frequency_table) * size, GFP_KERNEL); + if (!ftab) { + printk(KERN_ERR "%s: no memory for tables\n", __func__); + return -ENOMEM; + } + + ftab_size = size; + + ret = cpu_cur.info->calc_freqtable(&cpu_cur, ftab, size); + s3c_cpufreq_addfreq(ftab, ret, size, CPUFREQ_TABLE_END); + + return 0; +} + +static int __init s3c_cpufreq_initcall(void) +{ + int ret = 0; + + if (cpu_cur.info && cpu_cur.board) { + ret = s3c_cpufreq_initclks(); + if (ret) + goto out; + + /* get current settings */ + s3c_cpufreq_getcur(&cpu_cur); + s3c_cpufreq_show("cur", &cpu_cur); + + if (cpu_cur.board->auto_io) { + ret = s3c_cpufreq_auto_io(); + if (ret) { + printk(KERN_ERR "%s: failed to get io timing\n", + __func__); + goto out; + } + } + + if (cpu_cur.board->need_io && !cpu_cur.info->set_iotiming) { + printk(KERN_ERR "%s: no IO support registered\n", + __func__); + ret = -EINVAL; + goto out; + } + + if (!cpu_cur.info->need_pll) + cpu_cur.lock_pll = 1; + + s3c_cpufreq_update_loctkime(); + + s3c_cpufreq_freq_min(&cpu_cur.max, &cpu_cur.board->max, + &cpu_cur.info->max); + + if (cpu_cur.info->calc_freqtable) + s3c_cpufreq_build_freq(); + + ret = cpufreq_register_driver(&s3c24xx_driver); + } + + out: + return ret; +} + +late_initcall(s3c_cpufreq_initcall); + +/** + * s3c_plltab_register - register CPU PLL table. + * @plls: The list of PLL entries. + * @plls_no: The size of the PLL entries @plls. + * + * Register the given set of PLLs with the system. + */ +int __init s3c_plltab_register(struct cpufreq_frequency_table *plls, + unsigned int plls_no) +{ + struct cpufreq_frequency_table *vals; + unsigned int size; + + size = sizeof(struct cpufreq_frequency_table) * (plls_no + 1); + + vals = kmalloc(size, GFP_KERNEL); + if (vals) { + memcpy(vals, plls, size); + pll_reg = vals; + + /* write a terminating entry, we don't store it in the + * table that is stored in the kernel */ + vals += plls_no; + vals->frequency = CPUFREQ_TABLE_END; + + printk(KERN_INFO "cpufreq: %d PLL entries\n", plls_no); + } else + printk(KERN_ERR "cpufreq: no memory for PLL tables\n"); + + return vals ? 0 : -ENOMEM; +} diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index 1932b7e0da15..5447e60f3936 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -81,7 +81,7 @@ static struct cpu_table cpu_ids[] __initdata = { .map_io = s3c2410_map_io, .init_clocks = s3c2410_init_clocks, .init_uarts = s3c2410_init_uarts, - .init = s3c2410_init, + .init = s3c2410a_init, .name = name_s3c2410a }, { diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 4eb378c89a39..f52a92ce8dda 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -26,6 +26,8 @@ #include <asm/mach/irq.h> #include <mach/fb.h> #include <mach/hardware.h> +#include <mach/dma.h> +#include <mach/irqs.h> #include <asm/irq.h> #include <plat/regs-serial.h> @@ -180,25 +182,6 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd) } } -/* NAND Controller */ - -static struct resource s3c_nand_resource[] = { - [0] = { - .start = S3C24XX_PA_NAND, - .end = S3C24XX_PA_NAND + S3C24XX_SZ_NAND - 1, - .flags = IORESOURCE_MEM, - } -}; - -struct platform_device s3c_device_nand = { - .name = "s3c2410-nand", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_nand_resource), - .resource = s3c_nand_resource, -}; - -EXPORT_SYMBOL(s3c_device_nand); - /* USB Device (Gadget)*/ static struct resource s3c_usbgadget_resource[] = { @@ -348,7 +331,7 @@ struct platform_device s3c_device_adc = { /* HWMON */ struct platform_device s3c_device_hwmon = { - .name = "s3c24xx-hwmon", + .name = "s3c-hwmon", .id = -1, .dev.parent = &s3c_device_adc.dev, }; @@ -473,4 +456,52 @@ struct platform_device s3c_device_camif = { EXPORT_SYMBOL(s3c_device_camif); +/* AC97 */ + +static struct resource s3c_ac97_resource[] = { + [0] = { + .start = S3C2440_PA_AC97, + .end = S3C2440_PA_AC97 + S3C2440_SZ_AC97 -1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3C244x_AC97, + .end = IRQ_S3C244x_AC97, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .name = "PCM out", + .start = DMACH_PCM_OUT, + .end = DMACH_PCM_OUT, + .flags = IORESOURCE_DMA, + }, + [3] = { + .name = "PCM in", + .start = DMACH_PCM_IN, + .end = DMACH_PCM_IN, + .flags = IORESOURCE_DMA, + }, + [4] = { + .name = "Mic in", + .start = DMACH_MIC_IN, + .end = DMACH_MIC_IN, + .flags = IORESOURCE_DMA, + }, +}; + +static u64 s3c_device_ac97_dmamask = 0xffffffffUL; + +struct platform_device s3c_device_ac97 = { + .name = "s3c-ac97", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_ac97_resource), + .resource = s3c_ac97_resource, + .dev = { + .dma_mask = &s3c_device_ac97_dmamask, + .coherent_dma_mask = 0xffffffffUL + } +}; + +EXPORT_SYMBOL(s3c_device_ac97); + #endif // CONFIG_CPU_S32440 diff --git a/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h b/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h new file mode 100644 index 000000000000..efeb025affc7 --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/cpu-freq-core.h @@ -0,0 +1,282 @@ +/* arch/arm/plat-s3c/include/plat/cpu-freq.h + * + * Copyright (c) 2006,2007,2009 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C CPU frequency scaling support - core support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <plat/cpu-freq.h> + +struct seq_file; + +#define MAX_BANKS (8) +#define S3C2412_MAX_IO (8) + +/** + * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings + * @bankcon: The cached version of settings in this structure. + * @tacp: + * @tacs: Time from address valid to nCS asserted. + * @tcos: Time from nCS asserted to nOE or nWE asserted. + * @tacc: Time that nOE or nWE is asserted. + * @tcoh: Time nCS is held after nOE or nWE are released. + * @tcah: Time address is held for after + * @nwait_en: Whether nWAIT is enabled for this bank. + * + * This structure represents the IO timings for a S3C2410 style IO bank + * used by the CPU frequency support if it needs to change the settings + * of the IO. + */ +struct s3c2410_iobank_timing { + unsigned long bankcon; + unsigned int tacp; + unsigned int tacs; + unsigned int tcos; + unsigned int tacc; + unsigned int tcoh; /* nCS hold afrer nOE/nWE */ + unsigned int tcah; /* Address hold after nCS */ + unsigned char nwait_en; /* nWait enabled for bank. */ +}; + +/** + * struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO + * @idcy: The idle cycle time between transactions. + * @wstrd: nCS release to end of read cycle. + * @wstwr: nCS release to end of write cycle. + * @wstoen: nCS assertion to nOE assertion time. + * @wstwen: nCS assertion to nWE assertion time. + * @wstbrd: Burst ready delay. + * @smbidcyr: Register cache for smbidcyr value. + * @smbwstrd: Register cache for smbwstrd value. + * @smbwstwr: Register cache for smbwstwr value. + * @smbwstoen: Register cache for smbwstoen value. + * @smbwstwen: Register cache for smbwstwen value. + * @smbwstbrd: Register cache for smbwstbrd value. + * + * Timing information for a IO bank on an S3C2412 or similar system which + * uses a PL093 block. + */ +struct s3c2412_iobank_timing { + unsigned int idcy; + unsigned int wstrd; + unsigned int wstwr; + unsigned int wstoen; + unsigned int wstwen; + unsigned int wstbrd; + + /* register cache */ + unsigned char smbidcyr; + unsigned char smbwstrd; + unsigned char smbwstwr; + unsigned char smbwstoen; + unsigned char smbwstwen; + unsigned char smbwstbrd; +}; + +union s3c_iobank { + struct s3c2410_iobank_timing *io_2410; + struct s3c2412_iobank_timing *io_2412; +}; + +/** + * struct s3c_iotimings - Chip IO timings holder + * @bank: The timings for each IO bank. + */ +struct s3c_iotimings { + union s3c_iobank bank[MAX_BANKS]; +}; + +/** + * struct s3c_plltab - PLL table information. + * @vals: List of PLL values. + * @size: Size of the PLL table @vals. + */ +struct s3c_plltab { + struct s3c_pllval *vals; + int size; +}; + +/** + * struct s3c_cpufreq_config - current cpu frequency configuration + * @freq: The current settings for the core clocks. + * @max: Maxium settings, derived from core, board and user settings. + * @pll: The PLL table entry for the current PLL settings. + * @divs: The divisor settings for the core clocks. + * @info: The current core driver information. + * @board: The information for the board we are running on. + * @lock_pll: Set if the PLL settings cannot be changed. + * + * This is for the core drivers that need to know information about + * the current settings and values. It should not be needed by any + * device drivers. +*/ +struct s3c_cpufreq_config { + struct s3c_freq freq; + struct s3c_freq max; + struct cpufreq_frequency_table pll; + struct s3c_clkdivs divs; + struct s3c_cpufreq_info *info; /* for core, not drivers */ + struct s3c_cpufreq_board *board; + + unsigned int lock_pll:1; +}; + +/** + * struct s3c_cpufreq_info - Information for the CPU frequency driver. + * @name: The name of this implementation. + * @max: The maximum frequencies for the system. + * @latency: Transition latency to give to cpufreq. + * @locktime_m: The lock-time in uS for the MPLL. + * @locktime_u: The lock-time in uS for the UPLL. + * @locttime_bits: The number of bits each LOCKTIME field. + * @need_pll: Set if this driver needs to change the PLL values to acheive + * any frequency changes. This is really only need by devices like the + * S3C2410 where there is no or limited divider between the PLL and the + * ARMCLK. + * @resume_clocks: Update the clocks on resume. + * @get_iotiming: Get the current IO timing data, mainly for use at start. + * @set_iotiming: Update the IO timings from the cached copies calculated + * from the @calc_iotiming entry when changing the frequency. + * @calc_iotiming: Calculate and update the cached copies of the IO timings + * from the newly calculated frequencies. + * @calc_freqtable: Calculate (fill in) the given frequency table from the + * current frequency configuration. If the table passed in is NULL, + * then the return is the number of elements to be filled for allocation + * of the table. + * @set_refresh: Set the memory refresh configuration. + * @set_fvco: Set the PLL frequencies. + * @set_divs: Update the clock divisors. + * @calc_divs: Calculate the clock divisors. + */ +struct s3c_cpufreq_info { + const char *name; + struct s3c_freq max; + + unsigned int latency; + + unsigned int locktime_m; + unsigned int locktime_u; + unsigned char locktime_bits; + + unsigned int need_pll:1; + + /* driver routines */ + + void (*resume_clocks)(void); + + int (*get_iotiming)(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings); + + void (*set_iotiming)(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings); + + int (*calc_iotiming)(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings); + + int (*calc_freqtable)(struct s3c_cpufreq_config *cfg, + struct cpufreq_frequency_table *t, + size_t table_size); + + void (*debug_io_show)(struct seq_file *seq, + struct s3c_cpufreq_config *cfg, + union s3c_iobank *iob); + + void (*set_refresh)(struct s3c_cpufreq_config *cfg); + void (*set_fvco)(struct s3c_cpufreq_config *cfg); + void (*set_divs)(struct s3c_cpufreq_config *cfg); + int (*calc_divs)(struct s3c_cpufreq_config *cfg); +}; + +extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info); + +extern int s3c_plltab_register(struct cpufreq_frequency_table *plls, unsigned int plls_no); + +/* exports and utilities for debugfs */ +extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void); +extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void); + +extern void s3c2410_iotiming_debugfs(struct seq_file *seq, + struct s3c_cpufreq_config *cfg, + union s3c_iobank *iob); + +extern void s3c2412_iotiming_debugfs(struct seq_file *seq, + struct s3c_cpufreq_config *cfg, + union s3c_iobank *iob); + +#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS +#define s3c_cpufreq_debugfs_call(x) x +#else +#define s3c_cpufreq_debugfs_call(x) NULL +#endif + +/* Useful utility functions. */ + +extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *); + +/* S3C2410 and compatible exported functions */ + +extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg); + +extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot); + +extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings); + +extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot); + +extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg); + +/* S3C2412 compatible routines */ + +extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings); + +extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings); + +extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot); + +extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot); + +#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG +#define s3c_freq_dbg(x...) printk(KERN_INFO x) +#else +#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0) +#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */ + +#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG +#define s3c_freq_iodbg(x...) printk(KERN_INFO x) +#else +#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0) +#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */ + +static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table, + int index, size_t table_size, + unsigned int freq) +{ + if (index < 0) + return index; + + if (table) { + if (index >= table_size) + return -ENOMEM; + + s3c_freq_dbg("%s: { %d = %u kHz }\n", + __func__, index, freq); + + table[index].index = index; + table[index].frequency = freq; + } + + return index + 1; +} diff --git a/arch/arm/plat-s3c24xx/include/plat/fiq.h b/arch/arm/plat-s3c24xx/include/plat/fiq.h new file mode 100644 index 000000000000..8521b8372c5f --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/fiq.h @@ -0,0 +1,13 @@ +/* linux/include/asm-arm/plat-s3c24xx/fiq.h + * + * Copyright (c) 2009 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Header file for S3C24XX CPU FIQ support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +extern int s3c24xx_set_fiq(unsigned int irq, bool on); diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2410.h b/arch/arm/plat-s3c24xx/include/plat/s3c2410.h index a9ac9e29759e..b6deeef8f663 100644 --- a/arch/arm/plat-s3c24xx/include/plat/s3c2410.h +++ b/arch/arm/plat-s3c24xx/include/plat/s3c2410.h @@ -14,6 +14,7 @@ #ifdef CONFIG_CPU_S3C2410 extern int s3c2410_init(void); +extern int s3c2410a_init(void); extern void s3c2410_map_io(void); diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 958737775ad2..d02f5f02045e 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c @@ -493,6 +493,38 @@ s3c_irq_demux_extint4t7(unsigned int irq, } } +#ifdef CONFIG_FIQ +/** + * s3c24xx_set_fiq - set the FIQ routing + * @irq: IRQ number to route to FIQ on processor. + * @on: Whether to route @irq to the FIQ, or to remove the FIQ routing. + * + * Change the state of the IRQ to FIQ routing depending on @irq and @on. If + * @on is true, the @irq is checked to see if it can be routed and the + * interrupt controller updated to route the IRQ. If @on is false, the FIQ + * routing is cleared, regardless of which @irq is specified. + */ +int s3c24xx_set_fiq(unsigned int irq, bool on) +{ + u32 intmod; + unsigned offs; + + if (on) { + offs = irq - FIQ_START; + if (offs > 31) + return -EINVAL; + + intmod = 1 << offs; + } else { + intmod = 0; + } + + __raw_writel(intmod, S3C2410_INTMOD); + return 0; +} +#endif + + /* s3c24xx_init_irq * * Initialise S3C2410 IRQ system @@ -505,6 +537,10 @@ void __init s3c24xx_init_irq(void) int irqno; int i; +#ifdef CONFIG_FIQ + init_FIQ(); +#endif + irqdbf("s3c2410_init_irq: clearing interrupt status flags\n"); /* first, clear all interrupts pending... */ diff --git a/arch/arm/plat-s3c24xx/s3c2410-cpufreq-utils.c b/arch/arm/plat-s3c24xx/s3c2410-cpufreq-utils.c new file mode 100644 index 000000000000..43ea80190d87 --- /dev/null +++ b/arch/arm/plat-s3c24xx/s3c2410-cpufreq-utils.c @@ -0,0 +1,64 @@ +/* linux/arch/arm/plat-s3c24xx/s3c2410-cpufreq-utils.c + * + * Copyright (c) 2009 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX CPU Frequency scaling - utils for S3C2410/S3C2440/S3C2442 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/cpufreq.h> +#include <linux/io.h> + +#include <mach/map.h> +#include <mach/regs-mem.h> +#include <mach/regs-clock.h> + +#include <plat/cpu-freq-core.h> + +/** + * s3c2410_cpufreq_setrefresh - set SDRAM refresh value + * @cfg: The frequency configuration + * + * Set the SDRAM refresh value appropriately for the configured + * frequency. + */ +void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) +{ + struct s3c_cpufreq_board *board = cfg->board; + unsigned long refresh; + unsigned long refval; + + /* Reduce both the refresh time (in ns) and the frequency (in MHz) + * down to ensure that we do not overflow 32 bit numbers. + * + * This should work for HCLK up to 133MHz and refresh period up + * to 30usec. + */ + + refresh = (cfg->freq.hclk / 100) * (board->refresh / 10); + refresh = DIV_ROUND_UP(refresh, (1000 * 1000)); /* apply scale */ + refresh = (1 << 11) + 1 - refresh; + + s3c_freq_dbg("%s: refresh value %lu\n", __func__, refresh); + + refval = __raw_readl(S3C2410_REFRESH); + refval &= ~((1 << 12) - 1); + refval |= refresh; + __raw_writel(refval, S3C2410_REFRESH); +} + +/** + * s3c2410_set_fvco - set the PLL value + * @cfg: The frequency configuration + */ +void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg) +{ + __raw_writel(cfg->pll.index, S3C2410_MPLLCON); +} diff --git a/arch/arm/plat-s3c24xx/s3c2410-iotiming.c b/arch/arm/plat-s3c24xx/s3c2410-iotiming.c new file mode 100644 index 000000000000..d0a3a145cd4d --- /dev/null +++ b/arch/arm/plat-s3c24xx/s3c2410-iotiming.c @@ -0,0 +1,477 @@ +/* linux/arch/arm/plat-s3c24xx/s3c2410-iotiming.c + * + * Copyright (c) 2006,2008,2009 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX CPU Frequency scaling - IO timing for S3C2410/S3C2440/S3C2442 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/cpufreq.h> +#include <linux/seq_file.h> +#include <linux/io.h> + +#include <mach/map.h> +#include <mach/regs-mem.h> +#include <mach/regs-clock.h> + +#include <plat/cpu-freq-core.h> + +#define print_ns(x) ((x) / 10), ((x) % 10) + +/** + * s3c2410_print_timing - print bank timing data for debug purposes + * @pfx: The prefix to put on the output + * @timings: The timing inforamtion to print. +*/ +static void s3c2410_print_timing(const char *pfx, + struct s3c_iotimings *timings) +{ + struct s3c2410_iobank_timing *bt; + int bank; + + for (bank = 0; bank < MAX_BANKS; bank++) { + bt = timings->bank[bank].io_2410; + if (!bt) + continue; + + printk(KERN_DEBUG "%s %d: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, " + "Tcoh=%d.%d, Tcah=%d.%d\n", pfx, bank, + print_ns(bt->tacs), + print_ns(bt->tcos), + print_ns(bt->tacc), + print_ns(bt->tcoh), + print_ns(bt->tcah)); + } +} + +/** + * bank_reg - convert bank number to pointer to the control register. + * @bank: The IO bank number. + */ +static inline void __iomem *bank_reg(unsigned int bank) +{ + return S3C2410_BANKCON0 + (bank << 2); +} + +/** + * bank_is_io - test whether bank is used for IO + * @bankcon: The bank control register. + * + * This is a simplistic test to see if any BANKCON[x] is not an IO + * bank. It currently does not take into account whether BWSCON has + * an illegal width-setting in it, or if the pin connected to nCS[x] + * is actually being handled as a chip-select. + */ +static inline int bank_is_io(unsigned long bankcon) +{ + return !(bankcon & S3C2410_BANKCON_SDRAM); +} + +/** + * to_div - convert cycle time to divisor + * @cyc: The cycle time, in 10ths of nanoseconds. + * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. + * + * Convert the given cycle time into the divisor to use to obtain it from + * HCLK. +*/ +static inline unsigned int to_div(unsigned int cyc, unsigned int hclk_tns) +{ + if (cyc == 0) + return 0; + + return DIV_ROUND_UP(cyc, hclk_tns); +} + +/** + * calc_0124 - calculate divisor control for divisors that do /0, /1. /2 and /4 + * @cyc: The cycle time, in 10ths of nanoseconds. + * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. + * @v: Pointer to register to alter. + * @shift: The shift to get to the control bits. + * + * Calculate the divisor, and turn it into the correct control bits to + * set in the result, @v. + */ +static unsigned int calc_0124(unsigned int cyc, unsigned long hclk_tns, + unsigned long *v, int shift) +{ + unsigned int div = to_div(cyc, hclk_tns); + unsigned long val; + + s3c_freq_iodbg("%s: cyc=%d, hclk=%lu, shift=%d => div %d\n", + __func__, cyc, hclk_tns, shift, div); + + switch (div) { + case 0: + val = 0; + break; + case 1: + val = 1; + break; + case 2: + val = 2; + break; + case 3: + case 4: + val = 3; + break; + default: + return -1; + } + + *v |= val << shift; + return 0; +} + +int calc_tacp(unsigned int cyc, unsigned long hclk, unsigned long *v) +{ + /* Currently no support for Tacp calculations. */ + return 0; +} + +/** + * calc_tacc - calculate divisor control for tacc. + * @cyc: The cycle time, in 10ths of nanoseconds. + * @nwait_en: IS nWAIT enabled for this bank. + * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. + * @v: Pointer to register to alter. + * + * Calculate the divisor control for tACC, taking into account whether + * the bank has nWAIT enabled. The result is used to modify the value + * pointed to by @v. +*/ +static int calc_tacc(unsigned int cyc, int nwait_en, + unsigned long hclk_tns, unsigned long *v) +{ + unsigned int div = to_div(cyc, hclk_tns); + unsigned long val; + + s3c_freq_iodbg("%s: cyc=%u, nwait=%d, hclk=%lu => div=%u\n", + __func__, cyc, nwait_en, hclk_tns, div); + + /* if nWait enabled on an bank, Tacc must be at-least 4 cycles. */ + if (nwait_en && div < 4) + div = 4; + + switch (div) { + case 0: + val = 0; + break; + + case 1: + case 2: + case 3: + case 4: + val = div - 1; + break; + + case 5: + case 6: + val = 4; + break; + + case 7: + case 8: + val = 5; + break; + + case 9: + case 10: + val = 6; + break; + + case 11: + case 12: + case 13: + case 14: + val = 7; + break; + + default: + return -1; + } + + *v |= val << 8; + return 0; +} + +/** + * s3c2410_calc_bank - calculate bank timing infromation + * @cfg: The configuration we need to calculate for. + * @bt: The bank timing information. + * + * Given the cycle timine for a bank @bt, calculate the new BANKCON + * setting for the @cfg timing. This updates the timing information + * ready for the cpu frequency change. + */ +static int s3c2410_calc_bank(struct s3c_cpufreq_config *cfg, + struct s3c2410_iobank_timing *bt) +{ + unsigned long hclk = cfg->freq.hclk_tns; + unsigned long res; + int ret; + + res = bt->bankcon; + res &= (S3C2410_BANKCON_SDRAM | S3C2410_BANKCON_PMC16); + + /* tacp: 2,3,4,5 */ + /* tcah: 0,1,2,4 */ + /* tcoh: 0,1,2,4 */ + /* tacc: 1,2,3,4,6,7,10,14 (>4 for nwait) */ + /* tcos: 0,1,2,4 */ + /* tacs: 0,1,2,4 */ + + ret = calc_0124(bt->tacs, hclk, &res, S3C2410_BANKCON_Tacs_SHIFT); + ret |= calc_0124(bt->tcos, hclk, &res, S3C2410_BANKCON_Tcos_SHIFT); + ret |= calc_0124(bt->tcah, hclk, &res, S3C2410_BANKCON_Tcah_SHIFT); + ret |= calc_0124(bt->tcoh, hclk, &res, S3C2410_BANKCON_Tcoh_SHIFT); + + if (ret) + return -EINVAL; + + ret |= calc_tacp(bt->tacp, hclk, &res); + ret |= calc_tacc(bt->tacc, bt->nwait_en, hclk, &res); + + if (ret) + return -EINVAL; + + bt->bankcon = res; + return 0; +} + +static unsigned int tacc_tab[] = { + [0] = 1, + [1] = 2, + [2] = 3, + [3] = 4, + [4] = 6, + [5] = 9, + [6] = 10, + [7] = 14, +}; + +/** + * get_tacc - turn tACC value into cycle time + * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. + * @val: The bank timing register value, shifed down. + */ +static unsigned int get_tacc(unsigned long hclk_tns, + unsigned long val) +{ + val &= 7; + return hclk_tns * tacc_tab[val]; +} + +/** + * get_0124 - turn 0/1/2/4 divider into cycle time + * @hclk_tns: The cycle time for HCLK, in 10ths of nanoseconds. + * @val: The bank timing register value, shifed down. + */ +static unsigned int get_0124(unsigned long hclk_tns, + unsigned long val) +{ + val &= 3; + return hclk_tns * ((val == 3) ? 4 : val); +} + +/** + * s3c2410_iotiming_getbank - turn BANKCON into cycle time information + * @cfg: The frequency configuration + * @bt: The bank timing to fill in (uses cached BANKCON) + * + * Given the BANKCON setting in @bt and the current frequency settings + * in @cfg, update the cycle timing information. + */ +void s3c2410_iotiming_getbank(struct s3c_cpufreq_config *cfg, + struct s3c2410_iobank_timing *bt) +{ + unsigned long bankcon = bt->bankcon; + unsigned long hclk = cfg->freq.hclk_tns; + + bt->tcah = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcah_SHIFT); + bt->tcoh = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcoh_SHIFT); + bt->tcos = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcos_SHIFT); + bt->tacs = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tacs_SHIFT); + bt->tacc = get_tacc(hclk, bankcon >> S3C2410_BANKCON_Tacc_SHIFT); +} + +/** + * s3c2410_iotiming_debugfs - debugfs show io bank timing information + * @seq: The seq_file to write output to using seq_printf(). + * @cfg: The current configuration. + * @iob: The IO bank information to decode. + */ +void s3c2410_iotiming_debugfs(struct seq_file *seq, + struct s3c_cpufreq_config *cfg, + union s3c_iobank *iob) +{ + struct s3c2410_iobank_timing *bt = iob->io_2410; + unsigned long bankcon = bt->bankcon; + unsigned long hclk = cfg->freq.hclk_tns; + unsigned int tacs; + unsigned int tcos; + unsigned int tacc; + unsigned int tcoh; + unsigned int tcah; + + seq_printf(seq, "BANKCON=0x%08lx\n", bankcon); + + tcah = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcah_SHIFT); + tcoh = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcoh_SHIFT); + tcos = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tcos_SHIFT); + tacs = get_0124(hclk, bankcon >> S3C2410_BANKCON_Tacs_SHIFT); + tacc = get_tacc(hclk, bankcon >> S3C2410_BANKCON_Tacc_SHIFT); + + seq_printf(seq, + "\tRead: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, Tcoh=%d.%d, Tcah=%d.%d\n", + print_ns(bt->tacs), + print_ns(bt->tcos), + print_ns(bt->tacc), + print_ns(bt->tcoh), + print_ns(bt->tcah)); + + seq_printf(seq, + "\t Set: Tacs=%d.%d, Tcos=%d.%d, Tacc=%d.%d, Tcoh=%d.%d, Tcah=%d.%d\n", + print_ns(tacs), + print_ns(tcos), + print_ns(tacc), + print_ns(tcoh), + print_ns(tcah)); +} + +/** + * s3c2410_iotiming_calc - Calculate bank timing for frequency change. + * @cfg: The frequency configuration + * @iot: The IO timing information to fill out. + * + * Calculate the new values for the banks in @iot based on the new + * frequency information in @cfg. This is then used by s3c2410_iotiming_set() + * to update the timing when necessary. + */ +int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot) +{ + struct s3c2410_iobank_timing *bt; + unsigned long bankcon; + int bank; + int ret; + + for (bank = 0; bank < MAX_BANKS; bank++) { + bankcon = __raw_readl(bank_reg(bank)); + bt = iot->bank[bank].io_2410; + + if (!bt) + continue; + + bt->bankcon = bankcon; + + ret = s3c2410_calc_bank(cfg, bt); + if (ret) { + printk(KERN_ERR "%s: cannot calculate bank %d io\n", + __func__, bank); + goto err; + } + + s3c_freq_iodbg("%s: bank %d: con=%08lx\n", + __func__, bank, bt->bankcon); + } + + return 0; + err: + return ret; +} + +/** + * s3c2410_iotiming_set - set the IO timings from the given setup. + * @cfg: The frequency configuration + * @iot: The IO timing information to use. + * + * Set all the currently used IO bank timing information generated + * by s3c2410_iotiming_calc() once the core has validated that all + * the new values are within permitted bounds. + */ +void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot) +{ + struct s3c2410_iobank_timing *bt; + int bank; + + /* set the io timings from the specifier */ + + for (bank = 0; bank < MAX_BANKS; bank++) { + bt = iot->bank[bank].io_2410; + if (!bt) + continue; + + __raw_writel(bt->bankcon, bank_reg(bank)); + } +} + +/** + * s3c2410_iotiming_get - Get the timing information from current registers. + * @cfg: The frequency configuration + * @timings: The IO timing information to fill out. + * + * Calculate the @timings timing information from the current frequency + * information in @cfg, and the new frequency configur + * through all the IO banks, reading the state and then updating @iot + * as necessary. + * + * This is used at the moment on initialisation to get the current + * configuration so that boards do not have to carry their own setup + * if the timings are correct on initialisation. + */ + +int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings) +{ + struct s3c2410_iobank_timing *bt; + unsigned long bankcon; + unsigned long bwscon; + int bank; + + bwscon = __raw_readl(S3C2410_BWSCON); + + /* look through all banks to see what is currently set. */ + + for (bank = 0; bank < MAX_BANKS; bank++) { + bankcon = __raw_readl(bank_reg(bank)); + + if (!bank_is_io(bankcon)) + continue; + + s3c_freq_iodbg("%s: bank %d: con %08lx\n", + __func__, bank, bankcon); + + bt = kzalloc(sizeof(struct s3c2410_iobank_timing), GFP_KERNEL); + if (!bt) { + printk(KERN_ERR "%s: no memory for bank\n", __func__); + return -ENOMEM; + } + + /* find out in nWait is enabled for bank. */ + + if (bank != 0) { + unsigned long tmp = S3C2410_BWSCON_GET(bwscon, bank); + if (tmp & S3C2410_BWSCON_WS) + bt->nwait_en = 1; + } + + timings->bank[bank].io_2410 = bt; + bt->bankcon = bankcon; + + s3c2410_iotiming_getbank(cfg, bt); + } + + s3c2410_print_timing("get", timings); + return 0; +} diff --git a/arch/arm/plat-s3c24xx/s3c2412-iotiming.c b/arch/arm/plat-s3c24xx/s3c2412-iotiming.c new file mode 100644 index 000000000000..fd45e47facbc --- /dev/null +++ b/arch/arm/plat-s3c24xx/s3c2412-iotiming.c @@ -0,0 +1,285 @@ +/* linux/arch/arm/plat-s3c24xx/s3c2412-iotiming.c + * + * Copyright (c) 2006,2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2412/S3C2443 (PL093 based) IO timing support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/seq_file.h> +#include <linux/sysdev.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <linux/amba/pl093.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <mach/regs-s3c2412-mem.h> + +#include <plat/cpu.h> +#include <plat/cpu-freq-core.h> +#include <plat/clock.h> + +#define print_ns(x) ((x) / 10), ((x) % 10) + +/** + * s3c2412_print_timing - print timing infromation via printk. + * @pfx: The prefix to print each line with. + * @iot: The IO timing information + */ +static void s3c2412_print_timing(const char *pfx, struct s3c_iotimings *iot) +{ + struct s3c2412_iobank_timing *bt; + unsigned int bank; + + for (bank = 0; bank < MAX_BANKS; bank++) { + bt = iot->bank[bank].io_2412; + if (!bt) + continue; + + printk(KERN_DEBUG "%s: %d: idcy=%d.%d wstrd=%d.%d wstwr=%d,%d" + "wstoen=%d.%d wstwen=%d.%d wstbrd=%d.%d\n", pfx, bank, + print_ns(bt->idcy), + print_ns(bt->wstrd), + print_ns(bt->wstwr), + print_ns(bt->wstoen), + print_ns(bt->wstwen), + print_ns(bt->wstbrd)); + } +} + +/** + * to_div - turn a cycle length into a divisor setting. + * @cyc_tns: The cycle time in 10ths of nanoseconds. + * @clk_tns: The clock period in 10ths of nanoseconds. + */ +static inline unsigned int to_div(unsigned int cyc_tns, unsigned int clk_tns) +{ + return cyc_tns ? DIV_ROUND_UP(cyc_tns, clk_tns) : 0; +} + +/** + * calc_timing - calculate timing divisor value and check in range. + * @hwtm: The hardware timing in 10ths of nanoseconds. + * @clk_tns: The clock period in 10ths of nanoseconds. + * @err: Pointer to err variable to update in event of failure. + */ +static unsigned int calc_timing(unsigned int hwtm, unsigned int clk_tns, + unsigned int *err) +{ + unsigned int ret = to_div(hwtm, clk_tns); + + if (ret > 0xf) + *err = -EINVAL; + + return ret; +} + +/** + * s3c2412_calc_bank - calculate the bank divisor settings. + * @cfg: The current frequency configuration. + * @bt: The bank timing. + */ +static int s3c2412_calc_bank(struct s3c_cpufreq_config *cfg, + struct s3c2412_iobank_timing *bt) +{ + unsigned int hclk = cfg->freq.hclk_tns; + int err = 0; + + bt->smbidcyr = calc_timing(bt->idcy, hclk, &err); + bt->smbwstrd = calc_timing(bt->wstrd, hclk, &err); + bt->smbwstwr = calc_timing(bt->wstwr, hclk, &err); + bt->smbwstoen = calc_timing(bt->wstoen, hclk, &err); + bt->smbwstwen = calc_timing(bt->wstwen, hclk, &err); + bt->smbwstbrd = calc_timing(bt->wstbrd, hclk, &err); + + return err; +} + +/** + * s3c2412_iotiming_debugfs - debugfs show io bank timing information + * @seq: The seq_file to write output to using seq_printf(). + * @cfg: The current configuration. + * @iob: The IO bank information to decode. +*/ +void s3c2412_iotiming_debugfs(struct seq_file *seq, + struct s3c_cpufreq_config *cfg, + union s3c_iobank *iob) +{ + struct s3c2412_iobank_timing *bt = iob->io_2412; + + seq_printf(seq, + "\tRead: idcy=%d.%d wstrd=%d.%d wstwr=%d,%d" + "wstoen=%d.%d wstwen=%d.%d wstbrd=%d.%d\n", + print_ns(bt->idcy), + print_ns(bt->wstrd), + print_ns(bt->wstwr), + print_ns(bt->wstoen), + print_ns(bt->wstwen), + print_ns(bt->wstbrd)); +} + +/** + * s3c2412_iotiming_calc - calculate all the bank divisor settings. + * @cfg: The current frequency configuration. + * @iot: The bank timing information. + * + * Calculate the timing information for all the banks that are + * configured as IO, using s3c2412_calc_bank(). + */ +int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot) +{ + struct s3c2412_iobank_timing *bt; + int bank; + int ret; + + for (bank = 0; bank < MAX_BANKS; bank++) { + bt = iot->bank[bank].io_2412; + if (!bt) + continue; + + ret = s3c2412_calc_bank(cfg, bt); + if (ret) { + printk(KERN_ERR "%s: cannot calculate bank %d io\n", + __func__, bank); + goto err; + } + } + + return 0; + err: + return ret; +} + +/** + * s3c2412_iotiming_set - set the timing information + * @cfg: The current frequency configuration. + * @iot: The bank timing information. + * + * Set the IO bank information from the details calculated earlier from + * calling s3c2412_iotiming_calc(). + */ +void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *iot) +{ + struct s3c2412_iobank_timing *bt; + void __iomem *regs; + int bank; + + /* set the io timings from the specifier */ + + for (bank = 0; bank < MAX_BANKS; bank++) { + bt = iot->bank[bank].io_2412; + if (!bt) + continue; + + regs = S3C2412_SSMC_BANK(bank); + + __raw_writel(bt->smbidcyr, regs + SMBIDCYR); + __raw_writel(bt->smbwstrd, regs + SMBWSTRDR); + __raw_writel(bt->smbwstwr, regs + SMBWSTWRR); + __raw_writel(bt->smbwstoen, regs + SMBWSTOENR); + __raw_writel(bt->smbwstwen, regs + SMBWSTWENR); + __raw_writel(bt->smbwstbrd, regs + SMBWSTBRDR); + } +} + +static inline unsigned int s3c2412_decode_timing(unsigned int clock, u32 reg) +{ + return (reg & 0xf) * clock; +} + +static void s3c2412_iotiming_getbank(struct s3c_cpufreq_config *cfg, + struct s3c2412_iobank_timing *bt, + unsigned int bank) +{ + unsigned long clk = cfg->freq.hclk_tns; /* ssmc clock??? */ + void __iomem *regs = S3C2412_SSMC_BANK(bank); + + bt->idcy = s3c2412_decode_timing(clk, __raw_readl(regs + SMBIDCYR)); + bt->wstrd = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTRDR)); + bt->wstoen = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTOENR)); + bt->wstwen = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTWENR)); + bt->wstbrd = s3c2412_decode_timing(clk, __raw_readl(regs + SMBWSTBRDR)); +} + +/** + * bank_is_io - return true if bank is (possibly) IO. + * @bank: The bank number. + * @bankcfg: The value of S3C2412_EBI_BANKCFG. + */ +static inline bool bank_is_io(unsigned int bank, u32 bankcfg) +{ + if (bank < 2) + return true; + + return !(bankcfg & (1 << bank)); +} + +int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg, + struct s3c_iotimings *timings) +{ + struct s3c2412_iobank_timing *bt; + u32 bankcfg = __raw_readl(S3C2412_EBI_BANKCFG); + unsigned int bank; + + /* look through all banks to see what is currently set. */ + + for (bank = 0; bank < MAX_BANKS; bank++) { + if (!bank_is_io(bank, bankcfg)) + continue; + + bt = kzalloc(sizeof(struct s3c2412_iobank_timing), GFP_KERNEL); + if (!bt) { + printk(KERN_ERR "%s: no memory for bank\n", __func__); + return -ENOMEM; + } + + timings->bank[bank].io_2412 = bt; + s3c2412_iotiming_getbank(cfg, bt, bank); + } + + s3c2412_print_timing("get", timings); + return 0; +} + +/* this is in here as it is so small, it doesn't currently warrant a file + * to itself. We expect that any s3c24xx needing this is going to also + * need the iotiming support. + */ +void s3c2412_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) +{ + struct s3c_cpufreq_board *board = cfg->board; + u32 refresh; + + WARN_ON(board == NULL); + + /* Reduce both the refresh time (in ns) and the frequency (in MHz) + * down to ensure that we do not overflow 32 bit numbers. + * + * This should work for HCLK up to 133MHz and refresh period up + * to 30usec. + */ + + refresh = (cfg->freq.hclk / 100) * (board->refresh / 10); + refresh = DIV_ROUND_UP(refresh, (1000 * 1000)); /* apply scale */ + refresh &= ((1 << 16) - 1); + + s3c_freq_dbg("%s: refresh value %u\n", __func__, (unsigned int)refresh); + + __raw_writel(refresh, S3C2412_REFRESH); +} diff --git a/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c b/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c new file mode 100644 index 000000000000..ae2e6c604f27 --- /dev/null +++ b/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c @@ -0,0 +1,311 @@ +/* linux/arch/arm/plat-s3c24xx/s3c2440-cpufreq.c + * + * Copyright (c) 2006,2008,2009 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * Vincent Sanders <vince@simtec.co.uk> + * + * S3C2440/S3C2442 CPU Frequency scaling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/sysdev.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> + +#include <mach/hardware.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <mach/regs-clock.h> + +#include <plat/cpu.h> +#include <plat/cpu-freq-core.h> +#include <plat/clock.h> + +static struct clk *xtal; +static struct clk *fclk; +static struct clk *hclk; +static struct clk *armclk; + +/* HDIV: 1, 2, 3, 4, 6, 8 */ + +static inline int within_khz(unsigned long a, unsigned long b) +{ + long diff = a - b; + + return (diff >= -1000 && diff <= 1000); +} + +/** + * s3c2440_cpufreq_calcdivs - calculate divider settings + * @cfg: The cpu frequency settings. + * + * Calcualte the divider values for the given frequency settings + * specified in @cfg. The values are stored in @cfg for later use + * by the relevant set routine if the request settings can be reached. + */ +int s3c2440_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) +{ + unsigned int hdiv, pdiv; + unsigned long hclk, fclk, armclk; + unsigned long hclk_max; + + fclk = cfg->freq.fclk; + armclk = cfg->freq.armclk; + hclk_max = cfg->max.hclk; + + s3c_freq_dbg("%s: fclk is %lu, armclk %lu, max hclk %lu\n", + __func__, fclk, armclk, hclk_max); + + if (armclk > fclk) { + printk(KERN_WARNING "%s: armclk > fclk\n", __func__); + armclk = fclk; + } + + /* if we are in DVS, we need HCLK to be <= ARMCLK */ + if (armclk < fclk && armclk < hclk_max) + hclk_max = armclk; + + for (hdiv = 1; hdiv < 9; hdiv++) { + if (hdiv == 5 || hdiv == 7) + hdiv++; + + hclk = (fclk / hdiv); + if (hclk <= hclk_max || within_khz(hclk, hclk_max)) + break; + } + + s3c_freq_dbg("%s: hclk %lu, div %d\n", __func__, hclk, hdiv); + + if (hdiv > 8) + goto invalid; + + pdiv = (hclk > cfg->max.pclk) ? 2 : 1; + + if ((hclk / pdiv) > cfg->max.pclk) + pdiv++; + + s3c_freq_dbg("%s: pdiv %d\n", __func__, pdiv); + + if (pdiv > 2) + goto invalid; + + pdiv *= hdiv; + + /* calculate a valid armclk */ + + if (armclk < hclk) + armclk = hclk; + + /* if we're running armclk lower than fclk, this really means + * that the system should go into dvs mode, which means that + * armclk is connected to hclk. */ + if (armclk < fclk) { + cfg->divs.dvs = 1; + armclk = hclk; + } else + cfg->divs.dvs = 0; + + cfg->freq.armclk = armclk; + + /* store the result, and then return */ + + cfg->divs.h_divisor = hdiv; + cfg->divs.p_divisor = pdiv; + + return 0; + + invalid: + return -EINVAL; +} + +#define CAMDIVN_HCLK_HALF (S3C2440_CAMDIVN_HCLK3_HALF | \ + S3C2440_CAMDIVN_HCLK4_HALF) + +/** + * s3c2440_cpufreq_setdivs - set the cpu frequency divider settings + * @cfg: The cpu frequency settings. + * + * Set the divisors from the settings in @cfg, which where generated + * during the calculation phase by s3c2440_cpufreq_calcdivs(). + */ +static void s3c2440_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) +{ + unsigned long clkdiv, camdiv; + + s3c_freq_dbg("%s: divsiors: h=%d, p=%d\n", __func__, + cfg->divs.h_divisor, cfg->divs.p_divisor); + + clkdiv = __raw_readl(S3C2410_CLKDIVN); + camdiv = __raw_readl(S3C2440_CAMDIVN); + + clkdiv &= ~(S3C2440_CLKDIVN_HDIVN_MASK | S3C2440_CLKDIVN_PDIVN); + camdiv &= ~CAMDIVN_HCLK_HALF; + + switch (cfg->divs.h_divisor) { + case 1: + clkdiv |= S3C2440_CLKDIVN_HDIVN_1; + break; + + case 2: + clkdiv |= S3C2440_CLKDIVN_HDIVN_2; + break; + + case 6: + camdiv |= S3C2440_CAMDIVN_HCLK3_HALF; + case 3: + clkdiv |= S3C2440_CLKDIVN_HDIVN_3_6; + break; + + case 8: + camdiv |= S3C2440_CAMDIVN_HCLK4_HALF; + case 4: + clkdiv |= S3C2440_CLKDIVN_HDIVN_4_8; + break; + + default: + BUG(); /* we don't expect to get here. */ + } + + if (cfg->divs.p_divisor != cfg->divs.h_divisor) + clkdiv |= S3C2440_CLKDIVN_PDIVN; + + /* todo - set pclk. */ + + /* Write the divisors first with hclk intentionally halved so that + * when we write clkdiv we will under-frequency instead of over. We + * then make a short delay and remove the hclk halving if necessary. + */ + + __raw_writel(camdiv | CAMDIVN_HCLK_HALF, S3C2440_CAMDIVN); + __raw_writel(clkdiv, S3C2410_CLKDIVN); + + ndelay(20); + __raw_writel(camdiv, S3C2440_CAMDIVN); + + clk_set_parent(armclk, cfg->divs.dvs ? hclk : fclk); +} + +static int run_freq_for(unsigned long max_hclk, unsigned long fclk, + int *divs, + struct cpufreq_frequency_table *table, + size_t table_size) +{ + unsigned long freq; + int index = 0; + int div; + + for (div = *divs; div > 0; div = *divs++) { + freq = fclk / div; + + if (freq > max_hclk && div != 1) + continue; + + freq /= 1000; /* table is in kHz */ + index = s3c_cpufreq_addfreq(table, index, table_size, freq); + if (index < 0) + break; + } + + return index; +} + +static int hclk_divs[] = { 1, 2, 3, 4, 6, 8, -1 }; + +static int s3c2440_cpufreq_calctable(struct s3c_cpufreq_config *cfg, + struct cpufreq_frequency_table *table, + size_t table_size) +{ + int ret; + + WARN_ON(cfg->info == NULL); + WARN_ON(cfg->board == NULL); + + ret = run_freq_for(cfg->info->max.hclk, + cfg->info->max.fclk, + hclk_divs, + table, table_size); + + s3c_freq_dbg("%s: returning %d\n", __func__, ret); + + return ret; +} + +struct s3c_cpufreq_info s3c2440_cpufreq_info = { + .max = { + .fclk = 400000000, + .hclk = 133333333, + .pclk = 66666666, + }, + + .locktime_m = 300, + .locktime_u = 300, + .locktime_bits = 16, + + .name = "s3c244x", + .calc_iotiming = s3c2410_iotiming_calc, + .set_iotiming = s3c2410_iotiming_set, + .get_iotiming = s3c2410_iotiming_get, + .set_fvco = s3c2410_set_fvco, + + .set_refresh = s3c2410_cpufreq_setrefresh, + .set_divs = s3c2440_cpufreq_setdivs, + .calc_divs = s3c2440_cpufreq_calcdivs, + .calc_freqtable = s3c2440_cpufreq_calctable, + + .resume_clocks = s3c244x_setup_clocks, + + .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs), +}; + +static int s3c2440_cpufreq_add(struct sys_device *sysdev) +{ + xtal = s3c_cpufreq_clk_get(NULL, "xtal"); + hclk = s3c_cpufreq_clk_get(NULL, "hclk"); + fclk = s3c_cpufreq_clk_get(NULL, "fclk"); + armclk = s3c_cpufreq_clk_get(NULL, "armclk"); + + if (IS_ERR(xtal) || IS_ERR(hclk) || IS_ERR(fclk) || IS_ERR(armclk)) { + printk(KERN_ERR "%s: failed to get clocks\n", __func__); + return -ENOENT; + } + + return s3c_cpufreq_register(&s3c2440_cpufreq_info); +} + +static struct sysdev_driver s3c2440_cpufreq_driver = { + .add = s3c2440_cpufreq_add, +}; + +static int s3c2440_cpufreq_init(void) +{ + return sysdev_driver_register(&s3c2440_sysclass, + &s3c2440_cpufreq_driver); +} + +/* arch_initcall adds the clocks we need, so use subsys_initcall. */ +subsys_initcall(s3c2440_cpufreq_init); + +static struct sysdev_driver s3c2442_cpufreq_driver = { + .add = s3c2440_cpufreq_add, +}; + +static int s3c2442_cpufreq_init(void) +{ + return sysdev_driver_register(&s3c2442_sysclass, + &s3c2442_cpufreq_driver); +} + +subsys_initcall(s3c2442_cpufreq_init); diff --git a/arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c b/arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c new file mode 100644 index 000000000000..ff9443b233aa --- /dev/null +++ b/arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c @@ -0,0 +1,97 @@ +/* arch/arm/plat-s3c24xx/s3c2440-pll-12000000.c + * + * Copyright (c) 2006,2007 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * Vincent Sanders <vince@arm.linux.org.uk> + * + * S3C2440/S3C2442 CPU PLL tables (12MHz Crystal) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sysdev.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <plat/cpu.h> +#include <plat/cpu-freq-core.h> + +static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = { + { .frequency = 75000000, .index = PLLVAL(0x75, 3, 3), }, /* FVco 600.000000 */ + { .frequency = 80000000, .index = PLLVAL(0x98, 4, 3), }, /* FVco 640.000000 */ + { .frequency = 90000000, .index = PLLVAL(0x70, 2, 3), }, /* FVco 720.000000 */ + { .frequency = 100000000, .index = PLLVAL(0x5c, 1, 3), }, /* FVco 800.000000 */ + { .frequency = 110000000, .index = PLLVAL(0x66, 1, 3), }, /* FVco 880.000000 */ + { .frequency = 120000000, .index = PLLVAL(0x70, 1, 3), }, /* FVco 960.000000 */ + { .frequency = 150000000, .index = PLLVAL(0x75, 3, 2), }, /* FVco 600.000000 */ + { .frequency = 160000000, .index = PLLVAL(0x98, 4, 2), }, /* FVco 640.000000 */ + { .frequency = 170000000, .index = PLLVAL(0x4d, 1, 2), }, /* FVco 680.000000 */ + { .frequency = 180000000, .index = PLLVAL(0x70, 2, 2), }, /* FVco 720.000000 */ + { .frequency = 190000000, .index = PLLVAL(0x57, 1, 2), }, /* FVco 760.000000 */ + { .frequency = 200000000, .index = PLLVAL(0x5c, 1, 2), }, /* FVco 800.000000 */ + { .frequency = 210000000, .index = PLLVAL(0x84, 2, 2), }, /* FVco 840.000000 */ + { .frequency = 220000000, .index = PLLVAL(0x66, 1, 2), }, /* FVco 880.000000 */ + { .frequency = 230000000, .index = PLLVAL(0x6b, 1, 2), }, /* FVco 920.000000 */ + { .frequency = 240000000, .index = PLLVAL(0x70, 1, 2), }, /* FVco 960.000000 */ + { .frequency = 300000000, .index = PLLVAL(0x75, 3, 1), }, /* FVco 600.000000 */ + { .frequency = 310000000, .index = PLLVAL(0x93, 4, 1), }, /* FVco 620.000000 */ + { .frequency = 320000000, .index = PLLVAL(0x98, 4, 1), }, /* FVco 640.000000 */ + { .frequency = 330000000, .index = PLLVAL(0x66, 2, 1), }, /* FVco 660.000000 */ + { .frequency = 340000000, .index = PLLVAL(0x4d, 1, 1), }, /* FVco 680.000000 */ + { .frequency = 350000000, .index = PLLVAL(0xa7, 4, 1), }, /* FVco 700.000000 */ + { .frequency = 360000000, .index = PLLVAL(0x70, 2, 1), }, /* FVco 720.000000 */ + { .frequency = 370000000, .index = PLLVAL(0xb1, 4, 1), }, /* FVco 740.000000 */ + { .frequency = 380000000, .index = PLLVAL(0x57, 1, 1), }, /* FVco 760.000000 */ + { .frequency = 390000000, .index = PLLVAL(0x7a, 2, 1), }, /* FVco 780.000000 */ + { .frequency = 400000000, .index = PLLVAL(0x5c, 1, 1), }, /* FVco 800.000000 */ +}; + +static int s3c2440_plls12_add(struct sys_device *dev) +{ + struct clk *xtal_clk; + unsigned long xtal; + + xtal_clk = clk_get(NULL, "xtal"); + if (IS_ERR(xtal_clk)) + return PTR_ERR(xtal_clk); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + if (xtal == 12000000) { + printk(KERN_INFO "Using PLL table for 12MHz crystal\n"); + return s3c_plltab_register(s3c2440_plls_12, + ARRAY_SIZE(s3c2440_plls_12)); + } + + return 0; +} + +static struct sysdev_driver s3c2440_plls12_drv = { + .add = s3c2440_plls12_add, +}; + +static int __init s3c2440_pll_12mhz(void) +{ + return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_plls12_drv); + +} + +arch_initcall(s3c2440_pll_12mhz); + +static struct sysdev_driver s3c2442_plls12_drv = { + .add = s3c2440_plls12_add, +}; + +static int __init s3c2442_pll_12mhz(void) +{ + return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_plls12_drv); + +} + +arch_initcall(s3c2442_pll_12mhz); diff --git a/arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c b/arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c new file mode 100644 index 000000000000..7679af13a94d --- /dev/null +++ b/arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c @@ -0,0 +1,127 @@ +/* arch/arm/plat-s3c24xx/s3c2440-pll-16934400.c + * + * Copyright (c) 2006-2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * Vincent Sanders <vince@arm.linux.org.uk> + * + * S3C2440/S3C2442 CPU PLL tables (16.93444MHz Crystal) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sysdev.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <plat/cpu.h> +#include <plat/cpu-freq-core.h> + +static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = { + { .frequency = 78019200, .index = PLLVAL(121, 5, 3), }, /* FVco 624.153600 */ + { .frequency = 84067200, .index = PLLVAL(131, 5, 3), }, /* FVco 672.537600 */ + { .frequency = 90115200, .index = PLLVAL(141, 5, 3), }, /* FVco 720.921600 */ + { .frequency = 96163200, .index = PLLVAL(151, 5, 3), }, /* FVco 769.305600 */ + { .frequency = 102135600, .index = PLLVAL(185, 6, 3), }, /* FVco 817.084800 */ + { .frequency = 108259200, .index = PLLVAL(171, 5, 3), }, /* FVco 866.073600 */ + { .frequency = 114307200, .index = PLLVAL(127, 3, 3), }, /* FVco 914.457600 */ + { .frequency = 120234240, .index = PLLVAL(134, 3, 3), }, /* FVco 961.873920 */ + { .frequency = 126161280, .index = PLLVAL(141, 3, 3), }, /* FVco 1009.290240 */ + { .frequency = 132088320, .index = PLLVAL(148, 3, 3), }, /* FVco 1056.706560 */ + { .frequency = 138015360, .index = PLLVAL(155, 3, 3), }, /* FVco 1104.122880 */ + { .frequency = 144789120, .index = PLLVAL(163, 3, 3), }, /* FVco 1158.312960 */ + { .frequency = 150100363, .index = PLLVAL(187, 9, 2), }, /* FVco 600.401454 */ + { .frequency = 156038400, .index = PLLVAL(121, 5, 2), }, /* FVco 624.153600 */ + { .frequency = 162086400, .index = PLLVAL(126, 5, 2), }, /* FVco 648.345600 */ + { .frequency = 168134400, .index = PLLVAL(131, 5, 2), }, /* FVco 672.537600 */ + { .frequency = 174048000, .index = PLLVAL(177, 7, 2), }, /* FVco 696.192000 */ + { .frequency = 180230400, .index = PLLVAL(141, 5, 2), }, /* FVco 720.921600 */ + { .frequency = 186278400, .index = PLLVAL(124, 4, 2), }, /* FVco 745.113600 */ + { .frequency = 192326400, .index = PLLVAL(151, 5, 2), }, /* FVco 769.305600 */ + { .frequency = 198132480, .index = PLLVAL(109, 3, 2), }, /* FVco 792.529920 */ + { .frequency = 204271200, .index = PLLVAL(185, 6, 2), }, /* FVco 817.084800 */ + { .frequency = 210268800, .index = PLLVAL(141, 4, 2), }, /* FVco 841.075200 */ + { .frequency = 216518400, .index = PLLVAL(171, 5, 2), }, /* FVco 866.073600 */ + { .frequency = 222264000, .index = PLLVAL(97, 2, 2), }, /* FVco 889.056000 */ + { .frequency = 228614400, .index = PLLVAL(127, 3, 2), }, /* FVco 914.457600 */ + { .frequency = 234259200, .index = PLLVAL(158, 4, 2), }, /* FVco 937.036800 */ + { .frequency = 240468480, .index = PLLVAL(134, 3, 2), }, /* FVco 961.873920 */ + { .frequency = 246960000, .index = PLLVAL(167, 4, 2), }, /* FVco 987.840000 */ + { .frequency = 252322560, .index = PLLVAL(141, 3, 2), }, /* FVco 1009.290240 */ + { .frequency = 258249600, .index = PLLVAL(114, 2, 2), }, /* FVco 1032.998400 */ + { .frequency = 264176640, .index = PLLVAL(148, 3, 2), }, /* FVco 1056.706560 */ + { .frequency = 270950400, .index = PLLVAL(120, 2, 2), }, /* FVco 1083.801600 */ + { .frequency = 276030720, .index = PLLVAL(155, 3, 2), }, /* FVco 1104.122880 */ + { .frequency = 282240000, .index = PLLVAL(92, 1, 2), }, /* FVco 1128.960000 */ + { .frequency = 289578240, .index = PLLVAL(163, 3, 2), }, /* FVco 1158.312960 */ + { .frequency = 294235200, .index = PLLVAL(131, 2, 2), }, /* FVco 1176.940800 */ + { .frequency = 300200727, .index = PLLVAL(187, 9, 1), }, /* FVco 600.401454 */ + { .frequency = 306358690, .index = PLLVAL(191, 9, 1), }, /* FVco 612.717380 */ + { .frequency = 312076800, .index = PLLVAL(121, 5, 1), }, /* FVco 624.153600 */ + { .frequency = 318366720, .index = PLLVAL(86, 3, 1), }, /* FVco 636.733440 */ + { .frequency = 324172800, .index = PLLVAL(126, 5, 1), }, /* FVco 648.345600 */ + { .frequency = 330220800, .index = PLLVAL(109, 4, 1), }, /* FVco 660.441600 */ + { .frequency = 336268800, .index = PLLVAL(131, 5, 1), }, /* FVco 672.537600 */ + { .frequency = 342074880, .index = PLLVAL(93, 3, 1), }, /* FVco 684.149760 */ + { .frequency = 348096000, .index = PLLVAL(177, 7, 1), }, /* FVco 696.192000 */ + { .frequency = 355622400, .index = PLLVAL(118, 4, 1), }, /* FVco 711.244800 */ + { .frequency = 360460800, .index = PLLVAL(141, 5, 1), }, /* FVco 720.921600 */ + { .frequency = 366206400, .index = PLLVAL(165, 6, 1), }, /* FVco 732.412800 */ + { .frequency = 372556800, .index = PLLVAL(124, 4, 1), }, /* FVco 745.113600 */ + { .frequency = 378201600, .index = PLLVAL(126, 4, 1), }, /* FVco 756.403200 */ + { .frequency = 384652800, .index = PLLVAL(151, 5, 1), }, /* FVco 769.305600 */ + { .frequency = 391608000, .index = PLLVAL(177, 6, 1), }, /* FVco 783.216000 */ + { .frequency = 396264960, .index = PLLVAL(109, 3, 1), }, /* FVco 792.529920 */ + { .frequency = 402192000, .index = PLLVAL(87, 2, 1), }, /* FVco 804.384000 */ +}; + +static int s3c2440_plls169344_add(struct sys_device *dev) +{ + struct clk *xtal_clk; + unsigned long xtal; + + xtal_clk = clk_get(NULL, "xtal"); + if (IS_ERR(xtal_clk)) + return PTR_ERR(xtal_clk); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + if (xtal == 169344000) { + printk(KERN_INFO "Using PLL table for 16.9344MHz crystal\n"); + return s3c_plltab_register(s3c2440_plls_169344, + ARRAY_SIZE(s3c2440_plls_169344)); + } + + return 0; +} + +static struct sysdev_driver s3c2440_plls169344_drv = { + .add = s3c2440_plls169344_add, +}; + +static int __init s3c2440_pll_16934400(void) +{ + return sysdev_driver_register(&s3c2440_sysclass, + &s3c2440_plls169344_drv); + +} + +arch_initcall(s3c2440_pll_16934400); + +static struct sysdev_driver s3c2442_plls169344_drv = { + .add = s3c2440_plls169344_add, +}; + +static int __init s3c2442_pll_16934400(void) +{ + return sysdev_driver_register(&s3c2442_sysclass, + &s3c2442_plls169344_drv); + +} + +arch_initcall(s3c2442_pll_16934400); diff --git a/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c b/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c new file mode 100644 index 000000000000..89fcf5308cf6 --- /dev/null +++ b/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c @@ -0,0 +1,38 @@ +/* linux/arch/arm/plat-s3c24xx/spi-bus0-gpd8_9_10.c + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX SPI - gpio configuration for bus 1 on gpd8,9,10 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. +*/ + +#include <linux/kernel.h> +#include <linux/gpio.h> + +#include <mach/spi.h> +#include <mach/regs-gpio.h> + +void s3c24xx_spi_gpiocfg_bus1_gpd8_9_10(struct s3c2410_spi_info *spi, + int enable) +{ + + printk(KERN_INFO "%s(%d)\n", __func__, enable); + if (enable) { + s3c2410_gpio_cfgpin(S3C2410_GPD(10), S3C2440_GPD10_SPICLK1); + s3c2410_gpio_cfgpin(S3C2410_GPD(9), S3C2440_GPD9_SPIMOSI1); + s3c2410_gpio_cfgpin(S3C2410_GPD(8), S3C2440_GPD8_SPIMISO1); + s3c2410_gpio_pullup(S3C2410_GPD(10), 0); + s3c2410_gpio_pullup(S3C2410_GPD(9), 0); + } else { + s3c2410_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT); + s3c2410_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT); + s3c2410_gpio_pullup(S3C2410_GPD(10), 1); + s3c2410_gpio_pullup(S3C2410_GPD(9), 1); + s3c2410_gpio_pullup(S3C2410_GPD(8), 1); + } +} diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig index 5ebd8b425a54..bcfa778614d8 100644 --- a/arch/arm/plat-s3c64xx/Kconfig +++ b/arch/arm/plat-s3c64xx/Kconfig @@ -19,6 +19,7 @@ config PLAT_S3C64XX select S3C_GPIO_PULL_UPDOWN select S3C_GPIO_CFG_S3C24XX select S3C_GPIO_CFG_S3C64XX + select S3C_DEV_NAND select USB_ARCH_HAS_OHCI help Base platform code for any Samsung S3C64XX device diff --git a/arch/arm/plat-s3c64xx/Makefile b/arch/arm/plat-s3c64xx/Makefile index 3c8882cd6268..b85b4359e935 100644 --- a/arch/arm/plat-s3c64xx/Makefile +++ b/arch/arm/plat-s3c64xx/Makefile @@ -40,4 +40,5 @@ obj-$(CONFIG_S3C64XX_DMA) += dma.o obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o -obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
\ No newline at end of file +obj-$(CONFIG_S3C64XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o +obj-$(CONFIG_SND_S3C24XX_SOC) += dev-audio.o diff --git a/arch/arm/plat-s3c/dev-audio.c b/arch/arm/plat-s3c64xx/dev-audio.c index 1322beb40dd7..1322beb40dd7 100644 --- a/arch/arm/plat-s3c/dev-audio.c +++ b/arch/arm/plat-s3c64xx/dev-audio.c diff --git a/arch/arm/plat-s3c64xx/s3c6400-clock.c b/arch/arm/plat-s3c64xx/s3c6400-clock.c index 1debc1f9f987..febac1950d8e 100644 --- a/arch/arm/plat-s3c64xx/s3c6400-clock.c +++ b/arch/arm/plat-s3c64xx/s3c6400-clock.c @@ -153,7 +153,7 @@ static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk, u32 div; if (parent < rate) - return rate; + return parent; div = (parent / rate) - 1; if (div > armclk_mask) @@ -175,7 +175,7 @@ static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate) div = clk_get_rate(clk->parent) / rate; val = __raw_readl(S3C_CLK_DIV0); - val &= armclk_mask; + val &= ~armclk_mask; val |= (div - 1); __raw_writel(val, S3C_CLK_DIV0); diff --git a/arch/arm/plat-s5pc1xx/Kconfig b/arch/arm/plat-s5pc1xx/Kconfig new file mode 100644 index 000000000000..a8a711c3c064 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/Kconfig @@ -0,0 +1,50 @@ +# arch/arm/plat-s5pc1xx/Kconfig +# +# Copyright 2009 Samsung Electronics Co. +# Byungho Min <bhmin@samsung.com> +# +# Licensed under GPLv2 + +config PLAT_S5PC1XX + bool + depends on ARCH_S5PC1XX + default y + select PLAT_S3C + select ARM_VIC + select NO_IOPORT + select ARCH_REQUIRE_GPIOLIB + select S3C_GPIO_TRACK + select S3C_GPIO_PULL_UPDOWN + help + Base platform code for any Samsung S5PC1XX device + +if PLAT_S5PC1XX + +# Configuration options shared by all S3C64XX implementations + +config CPU_S5PC100_INIT + bool + help + Common initialisation code for the S5PC1XX + +config CPU_S5PC100_CLOCK + bool + help + Common clock support code for the S5PC1XX + +# platform specific device setup + +config S5PC100_SETUP_I2C0 + bool + default y + help + Common setup code for i2c bus 0. + + Note, currently since i2c0 is always compiled, this setup helper + is always compiled with it. + +config S5PC100_SETUP_I2C1 + bool + help + Common setup code for i2c bus 1. +endif diff --git a/arch/arm/plat-s5pc1xx/Makefile b/arch/arm/plat-s5pc1xx/Makefile new file mode 100644 index 000000000000..f1ecb2c37ee2 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/Makefile @@ -0,0 +1,26 @@ +# arch/arm/plat-s5pc1xx/Makefile +# +# Copyright 2009 Samsung Electronics Co. +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := dummy.o +obj- := + +# Core files + +obj-y += dev-uart.o +obj-y += cpu.o +obj-y += irq.o + +# CPU support + +obj-$(CONFIG_CPU_S5PC100_INIT) += s5pc100-init.o +obj-$(CONFIG_CPU_S5PC100_CLOCK) += s5pc100-clock.o + +# Device setup + +obj-$(CONFIG_S5PC100_SETUP_I2C0) += setup-i2c0.o +obj-$(CONFIG_S5PC100_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/plat-s5pc1xx/cpu.c b/arch/arm/plat-s5pc1xx/cpu.c new file mode 100644 index 000000000000..715a7330794d --- /dev/null +++ b/arch/arm/plat-s5pc1xx/cpu.c @@ -0,0 +1,112 @@ +/* linux/arch/arm/plat-s5pc1xx/cpu.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC1XX CPU Support + * + * Based on plat-s3c64xx/cpu.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/serial_core.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <asm/mach/map.h> + +#include <plat/regs-serial.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/clock.h> + +#include <plat/s5pc100.h> + +/* table of supported CPUs */ + +static const char name_s5pc100[] = "S5PC100"; + +static struct cpu_table cpu_ids[] __initdata = { + { + .idcode = 0x43100000, + .idmask = 0xfffff000, + .map_io = s5pc100_map_io, + .init_clocks = s5pc100_init_clocks, + .init_uarts = s5pc100_init_uarts, + .init = s5pc100_init, + .name = name_s5pc100, + }, +}; +/* minimal IO mapping */ + +/* see notes on uart map in arch/arm/mach-s5pc100/include/mach/debug-macro.S */ +#define UART_OFFS (S3C_PA_UART & 0xffff) + +static struct map_desc s5pc1xx_iodesc[] __initdata = { + { + .virtual = (unsigned long)S5PC1XX_VA_CHIPID, + .pfn = __phys_to_pfn(S5PC1XX_PA_CHIPID), + .length = SZ_16, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5PC1XX_VA_CLK, + .pfn = __phys_to_pfn(S5PC1XX_PA_CLK), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5PC1XX_VA_PWR, + .pfn = __phys_to_pfn(S5PC1XX_PA_PWR), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)(S5PC1XX_VA_UART), + .pfn = __phys_to_pfn(S5PC1XX_PA_UART), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5PC1XX_VA_VIC(0), + .pfn = __phys_to_pfn(S5PC1XX_PA_VIC(0)), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5PC1XX_VA_VIC(1), + .pfn = __phys_to_pfn(S5PC1XX_PA_VIC(1)), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5PC1XX_VA_VIC(2), + .pfn = __phys_to_pfn(S5PC1XX_PA_VIC(2)), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long)S5PC1XX_VA_TIMER, + .pfn = __phys_to_pfn(S5PC1XX_PA_TIMER), + .length = SZ_256, + .type = MT_DEVICE, + }, +}; + +/* read cpu identification code */ + +void __init s5pc1xx_init_io(struct map_desc *mach_desc, int size) +{ + unsigned long idcode; + + /* initialise the io descriptors we need for initialisation */ + iotable_init(s5pc1xx_iodesc, ARRAY_SIZE(s5pc1xx_iodesc)); + iotable_init(mach_desc, size); + + idcode = __raw_readl(S5PC1XX_VA_CHIPID); + s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids)); +} diff --git a/arch/arm/plat-s5pc1xx/dev-uart.c b/arch/arm/plat-s5pc1xx/dev-uart.c new file mode 100644 index 000000000000..f749bc5407b5 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/dev-uart.c @@ -0,0 +1,174 @@ +/* linux/arch/arm/plat-s5pc1xx/dev-uart.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Based on plat-s3c64xx/dev-uart.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/devs.h> + +/* Serial port registrations */ + +/* 64xx uarts are closer together */ + +static struct resource s5pc1xx_uart0_resource[] = { + [0] = { + .start = S3C_PA_UART0, + .end = S3C_PA_UART0 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX0, + .end = IRQ_S3CUART_RX0, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX0, + .end = IRQ_S3CUART_TX0, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR0, + .end = IRQ_S3CUART_ERR0, + .flags = IORESOURCE_IRQ, + } +}; + +static struct resource s5pc1xx_uart1_resource[] = { + [0] = { + .start = S3C_PA_UART1, + .end = S3C_PA_UART1 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX1, + .end = IRQ_S3CUART_RX1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX1, + .end = IRQ_S3CUART_TX1, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR1, + .end = IRQ_S3CUART_ERR1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s5pc1xx_uart2_resource[] = { + [0] = { + .start = S3C_PA_UART2, + .end = S3C_PA_UART2 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX2, + .end = IRQ_S3CUART_RX2, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX2, + .end = IRQ_S3CUART_TX2, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR2, + .end = IRQ_S3CUART_ERR2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource s5pc1xx_uart3_resource[] = { + [0] = { + .start = S3C_PA_UART3, + .end = S3C_PA_UART3 + 0x100, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_S3CUART_RX3, + .end = IRQ_S3CUART_RX3, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_S3CUART_TX3, + .end = IRQ_S3CUART_TX3, + .flags = IORESOURCE_IRQ, + + }, + [3] = { + .start = IRQ_S3CUART_ERR3, + .end = IRQ_S3CUART_ERR3, + .flags = IORESOURCE_IRQ, + }, +}; + + +struct s3c24xx_uart_resources s5pc1xx_uart_resources[] __initdata = { + [0] = { + .resources = s5pc1xx_uart0_resource, + .nr_resources = ARRAY_SIZE(s5pc1xx_uart0_resource), + }, + [1] = { + .resources = s5pc1xx_uart1_resource, + .nr_resources = ARRAY_SIZE(s5pc1xx_uart1_resource), + }, + [2] = { + .resources = s5pc1xx_uart2_resource, + .nr_resources = ARRAY_SIZE(s5pc1xx_uart2_resource), + }, + [3] = { + .resources = s5pc1xx_uart3_resource, + .nr_resources = ARRAY_SIZE(s5pc1xx_uart3_resource), + }, +}; + +/* uart devices */ + +static struct platform_device s3c24xx_uart_device0 = { + .id = 0, +}; + +static struct platform_device s3c24xx_uart_device1 = { + .id = 1, +}; + +static struct platform_device s3c24xx_uart_device2 = { + .id = 2, +}; + +static struct platform_device s3c24xx_uart_device3 = { + .id = 3, +}; + +struct platform_device *s3c24xx_uart_src[4] = { + &s3c24xx_uart_device0, + &s3c24xx_uart_device1, + &s3c24xx_uart_device2, + &s3c24xx_uart_device3, +}; + +struct platform_device *s3c24xx_uart_devs[4] = { +}; + diff --git a/arch/arm/plat-s5pc1xx/include/plat/irqs.h b/arch/arm/plat-s5pc1xx/include/plat/irqs.h new file mode 100644 index 000000000000..f07d8c3b25d6 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/include/plat/irqs.h @@ -0,0 +1,182 @@ +/* linux/arch/arm/plat-s5pc1xx/include/plat/irqs.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC1XX - Common IRQ support + * + * Based on plat-s3c64xx/include/plat/irqs.h + */ + +#ifndef __ASM_PLAT_S5PC1XX_IRQS_H +#define __ASM_PLAT_S5PC1XX_IRQS_H __FILE__ + +/* we keep the first set of CPU IRQs out of the range of + * the ISA space, so that the PC104 has them to itself + * and we don't end up having to do horrible things to the + * standard ISA drivers.... + * + * note, since we're using the VICs, our start must be a + * mulitple of 32 to allow the common code to work + */ + +#define S3C_IRQ_OFFSET (32) + +#define S3C_IRQ(x) ((x) + S3C_IRQ_OFFSET) + +#define S3C_VIC0_BASE S3C_IRQ(0) +#define S3C_VIC1_BASE S3C_IRQ(32) +#define S3C_VIC2_BASE S3C_IRQ(64) + +/* UART interrupts, each UART has 4 intterupts per channel so + * use the space between the ISA and S3C main interrupts. Note, these + * are not in the same order as the S3C24XX series! */ + +#define IRQ_S3CUART_BASE0 (16) +#define IRQ_S3CUART_BASE1 (20) +#define IRQ_S3CUART_BASE2 (24) +#define IRQ_S3CUART_BASE3 (28) + +#define UART_IRQ_RXD (0) +#define UART_IRQ_ERR (1) +#define UART_IRQ_TXD (2) +#define UART_IRQ_MODEM (3) + +#define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR) + +#define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD) +#define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD) +#define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR) + +/* VIC based IRQs */ + +#define S5PC1XX_IRQ_VIC0(x) (S3C_VIC0_BASE + (x)) +#define S5PC1XX_IRQ_VIC1(x) (S3C_VIC1_BASE + (x)) +#define S5PC1XX_IRQ_VIC2(x) (S3C_VIC2_BASE + (x)) + +/* + * VIC0: system, DMA, timer + */ +#define IRQ_EINT0 S5PC1XX_IRQ_VIC0(0) +#define IRQ_EINT1 S5PC1XX_IRQ_VIC0(1) +#define IRQ_EINT2 S5PC1XX_IRQ_VIC0(2) +#define IRQ_EINT3 S5PC1XX_IRQ_VIC0(3) +#define IRQ_EINT4 S5PC1XX_IRQ_VIC0(4) +#define IRQ_EINT5 S5PC1XX_IRQ_VIC0(5) +#define IRQ_EINT6 S5PC1XX_IRQ_VIC0(6) +#define IRQ_EINT7 S5PC1XX_IRQ_VIC0(7) +#define IRQ_EINT8 S5PC1XX_IRQ_VIC0(8) +#define IRQ_EINT9 S5PC1XX_IRQ_VIC0(9) +#define IRQ_EINT10 S5PC1XX_IRQ_VIC0(10) +#define IRQ_EINT11 S5PC1XX_IRQ_VIC0(11) +#define IRQ_EINT12 S5PC1XX_IRQ_VIC0(12) +#define IRQ_EINT13 S5PC1XX_IRQ_VIC0(13) +#define IRQ_EINT14 S5PC1XX_IRQ_VIC0(14) +#define IRQ_EINT15 S5PC1XX_IRQ_VIC0(15) +#define IRQ_EINT16_31 S5PC1XX_IRQ_VIC0(16) +#define IRQ_BATF S5PC1XX_IRQ_VIC0(17) +#define IRQ_MDMA S5PC1XX_IRQ_VIC0(18) +#define IRQ_PDMA0 S5PC1XX_IRQ_VIC0(19) +#define IRQ_PDMA1 S5PC1XX_IRQ_VIC0(20) +#define IRQ_TIMER0 S5PC1XX_IRQ_VIC0(21) +#define IRQ_TIMER1 S5PC1XX_IRQ_VIC0(22) +#define IRQ_TIMER2 S5PC1XX_IRQ_VIC0(23) +#define IRQ_TIMER3 S5PC1XX_IRQ_VIC0(24) +#define IRQ_TIMER4 S5PC1XX_IRQ_VIC0(25) +#define IRQ_SYSTIMER S5PC1XX_IRQ_VIC0(26) +#define IRQ_WDT S5PC1XX_IRQ_VIC0(27) +#define IRQ_RTC_ALARM S5PC1XX_IRQ_VIC0(28) +#define IRQ_RTC_TIC S5PC1XX_IRQ_VIC0(29) +#define IRQ_GPIOINT S5PC1XX_IRQ_VIC0(30) + +/* + * VIC1: ARM, power, memory, connectivity + */ +#define IRQ_CORTEX0 S5PC1XX_IRQ_VIC1(0) +#define IRQ_CORTEX1 S5PC1XX_IRQ_VIC1(1) +#define IRQ_CORTEX2 S5PC1XX_IRQ_VIC1(2) +#define IRQ_CORTEX3 S5PC1XX_IRQ_VIC1(3) +#define IRQ_CORTEX4 S5PC1XX_IRQ_VIC1(4) +#define IRQ_IEMAPC S5PC1XX_IRQ_VIC1(5) +#define IRQ_IEMIEC S5PC1XX_IRQ_VIC1(6) +#define IRQ_ONENAND S5PC1XX_IRQ_VIC1(7) +#define IRQ_NFC S5PC1XX_IRQ_VIC1(8) +#define IRQ_CFC S5PC1XX_IRQ_VIC1(9) +#define IRQ_UART0 S5PC1XX_IRQ_VIC1(10) +#define IRQ_UART1 S5PC1XX_IRQ_VIC1(11) +#define IRQ_UART2 S5PC1XX_IRQ_VIC1(12) +#define IRQ_UART3 S5PC1XX_IRQ_VIC1(13) +#define IRQ_IIC S5PC1XX_IRQ_VIC1(14) +#define IRQ_SPI0 S5PC1XX_IRQ_VIC1(15) +#define IRQ_SPI1 S5PC1XX_IRQ_VIC1(16) +#define IRQ_SPI2 S5PC1XX_IRQ_VIC1(17) +#define IRQ_IRDA S5PC1XX_IRQ_VIC1(18) +#define IRQ_CAN0 S5PC1XX_IRQ_VIC1(19) +#define IRQ_CAN1 S5PC1XX_IRQ_VIC1(20) +#define IRQ_HSIRX S5PC1XX_IRQ_VIC1(21) +#define IRQ_HSITX S5PC1XX_IRQ_VIC1(22) +#define IRQ_UHOST S5PC1XX_IRQ_VIC1(23) +#define IRQ_OTG S5PC1XX_IRQ_VIC1(24) +#define IRQ_MSM S5PC1XX_IRQ_VIC1(25) +#define IRQ_HSMMC0 S5PC1XX_IRQ_VIC1(26) +#define IRQ_HSMMC1 S5PC1XX_IRQ_VIC1(27) +#define IRQ_HSMMC2 S5PC1XX_IRQ_VIC1(28) +#define IRQ_MIPICSI S5PC1XX_IRQ_VIC1(29) +#define IRQ_MIPIDSI S5PC1XX_IRQ_VIC1(30) + +/* + * VIC2: multimedia, audio, security + */ +#define IRQ_LCD0 S5PC1XX_IRQ_VIC2(0) +#define IRQ_LCD1 S5PC1XX_IRQ_VIC2(1) +#define IRQ_LCD2 S5PC1XX_IRQ_VIC2(2) +#define IRQ_LCD3 S5PC1XX_IRQ_VIC2(3) +#define IRQ_ROTATOR S5PC1XX_IRQ_VIC2(4) +#define IRQ_FIMC0 S5PC1XX_IRQ_VIC2(5) +#define IRQ_FIMC1 S5PC1XX_IRQ_VIC2(6) +#define IRQ_FIMC2 S5PC1XX_IRQ_VIC2(7) +#define IRQ_JPEG S5PC1XX_IRQ_VIC2(8) +#define IRQ_2D S5PC1XX_IRQ_VIC2(9) +#define IRQ_3D S5PC1XX_IRQ_VIC2(10) +#define IRQ_MIXER S5PC1XX_IRQ_VIC2(11) +#define IRQ_HDMI S5PC1XX_IRQ_VIC2(12) +#define IRQ_IIC1 S5PC1XX_IRQ_VIC2(13) +#define IRQ_MFC S5PC1XX_IRQ_VIC2(14) +#define IRQ_TVENC S5PC1XX_IRQ_VIC2(15) +#define IRQ_I2S0 S5PC1XX_IRQ_VIC2(16) +#define IRQ_I2S1 S5PC1XX_IRQ_VIC2(17) +#define IRQ_I2S2 S5PC1XX_IRQ_VIC2(18) +#define IRQ_AC97 S5PC1XX_IRQ_VIC2(19) +#define IRQ_PCM0 S5PC1XX_IRQ_VIC2(20) +#define IRQ_PCM1 S5PC1XX_IRQ_VIC2(21) +#define IRQ_SPDIF S5PC1XX_IRQ_VIC2(22) +#define IRQ_ADC S5PC1XX_IRQ_VIC2(23) +#define IRQ_PENDN S5PC1XX_IRQ_VIC2(24) +#define IRQ_TC IRQ_PENDN +#define IRQ_KEYPAD S5PC1XX_IRQ_VIC2(25) +#define IRQ_CG S5PC1XX_IRQ_VIC2(26) +#define IRQ_SEC S5PC1XX_IRQ_VIC2(27) +#define IRQ_SECRX S5PC1XX_IRQ_VIC2(28) +#define IRQ_SECTX S5PC1XX_IRQ_VIC2(29) +#define IRQ_SDMIRQ S5PC1XX_IRQ_VIC2(30) +#define IRQ_SDMFIQ S5PC1XX_IRQ_VIC2(31) + +#define S3C_IRQ_EINT_BASE (IRQ_SDMFIQ + 1) + +#define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE) +#define IRQ_EINT(x) S3C_EINT(x) + +#define NR_IRQS (IRQ_EINT(31)+1) + +#endif /* __ASM_PLAT_S5PC1XX_IRQS_H */ + diff --git a/arch/arm/plat-s5pc1xx/include/plat/pll.h b/arch/arm/plat-s5pc1xx/include/plat/pll.h new file mode 100644 index 000000000000..21afef1573e7 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/include/plat/pll.h @@ -0,0 +1,38 @@ +/* arch/arm/plat-s5pc1xx/include/plat/pll.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC1XX PLL code + * + * Based on plat-s3c64xx/include/plat/pll.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#define S5P_PLL_MDIV_MASK ((1 << (25-16+1)) - 1) +#define S5P_PLL_PDIV_MASK ((1 << (13-8+1)) - 1) +#define S5P_PLL_SDIV_MASK ((1 << (2-0+1)) - 1) +#define S5P_PLL_MDIV_SHIFT (16) +#define S5P_PLL_PDIV_SHIFT (8) +#define S5P_PLL_SDIV_SHIFT (0) + +#include <asm/div64.h> + +static inline unsigned long s5pc1xx_get_pll(unsigned long baseclk, + u32 pllcon) +{ + u32 mdiv, pdiv, sdiv; + u64 fvco = baseclk; + + mdiv = (pllcon >> S5P_PLL_MDIV_SHIFT) & S5P_PLL_MDIV_MASK; + pdiv = (pllcon >> S5P_PLL_PDIV_SHIFT) & S5P_PLL_PDIV_MASK; + sdiv = (pllcon >> S5P_PLL_SDIV_SHIFT) & S5P_PLL_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} diff --git a/arch/arm/plat-s5pc1xx/include/plat/regs-clock.h b/arch/arm/plat-s5pc1xx/include/plat/regs-clock.h new file mode 100644 index 000000000000..75c8390cb827 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/include/plat/regs-clock.h @@ -0,0 +1,421 @@ +/* arch/arm/plat-s5pc1xx/include/plat/regs-clock.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC1XX clock register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __PLAT_REGS_CLOCK_H +#define __PLAT_REGS_CLOCK_H __FILE__ + +#define S5PC1XX_CLKREG(x) (S5PC1XX_VA_CLK + (x)) + +#define S5PC1XX_APLL_LOCK S5PC1XX_CLKREG(0x00) +#define S5PC1XX_MPLL_LOCK S5PC1XX_CLKREG(0x04) +#define S5PC1XX_EPLL_LOCK S5PC1XX_CLKREG(0x08) +#define S5PC100_HPLL_LOCK S5PC1XX_CLKREG(0x0C) + +#define S5PC1XX_APLL_CON S5PC1XX_CLKREG(0x100) +#define S5PC1XX_MPLL_CON S5PC1XX_CLKREG(0x104) +#define S5PC1XX_EPLL_CON S5PC1XX_CLKREG(0x108) +#define S5PC100_HPLL_CON S5PC1XX_CLKREG(0x10C) + +#define S5PC1XX_CLK_SRC0 S5PC1XX_CLKREG(0x200) +#define S5PC1XX_CLK_SRC1 S5PC1XX_CLKREG(0x204) +#define S5PC1XX_CLK_SRC2 S5PC1XX_CLKREG(0x208) +#define S5PC1XX_CLK_SRC3 S5PC1XX_CLKREG(0x20C) + +#define S5PC1XX_CLK_DIV0 S5PC1XX_CLKREG(0x300) +#define S5PC1XX_CLK_DIV1 S5PC1XX_CLKREG(0x304) +#define S5PC1XX_CLK_DIV2 S5PC1XX_CLKREG(0x308) +#define S5PC1XX_CLK_DIV3 S5PC1XX_CLKREG(0x30C) +#define S5PC1XX_CLK_DIV4 S5PC1XX_CLKREG(0x310) + +#define S5PC100_CLK_OUT S5PC1XX_CLKREG(0x400) + +#define S5PC100_CLKGATE_D00 S5PC1XX_CLKREG(0x500) +#define S5PC100_CLKGATE_D01 S5PC1XX_CLKREG(0x504) +#define S5PC100_CLKGATE_D02 S5PC1XX_CLKREG(0x508) + +#define S5PC100_CLKGATE_D10 S5PC1XX_CLKREG(0x520) +#define S5PC100_CLKGATE_D11 S5PC1XX_CLKREG(0x524) +#define S5PC100_CLKGATE_D12 S5PC1XX_CLKREG(0x528) +#define S5PC100_CLKGATE_D13 S5PC1XX_CLKREG(0x52C) +#define S5PC100_CLKGATE_D14 S5PC1XX_CLKREG(0x530) +#define S5PC100_CLKGATE_D15 S5PC1XX_CLKREG(0x534) + +#define S5PC100_CLKGATE_D20 S5PC1XX_CLKREG(0x540) + +#define S5PC100_SCLKGATE0 S5PC1XX_CLKREG(0x560) +#define S5PC100_SCLKGATE1 S5PC1XX_CLKREG(0x564) + +#define S5PC100_OTHERS S5PC1XX_CLKREG(0x8200) + +#define S5PC1XX_EPLL_EN (1<<31) +#define S5PC1XX_EPLL_MASK 0xffffffff +#define S5PC1XX_EPLLVAL(_m, _p, _s) ((_m) << 16 | ((_p) << 8) | ((_s))) + +/* CLKSRC0 */ +#define S5PC1XX_CLKSRC0_APLL_MASK (0x1<<0) +#define S5PC1XX_CLKSRC0_APLL_SHIFT (0) +#define S5PC1XX_CLKSRC0_MPLL_MASK (0x1<<4) +#define S5PC1XX_CLKSRC0_MPLL_SHIFT (4) +#define S5PC1XX_CLKSRC0_EPLL_MASK (0x1<<8) +#define S5PC1XX_CLKSRC0_EPLL_SHIFT (8) +#define S5PC100_CLKSRC0_HPLL_MASK (0x1<<12) +#define S5PC100_CLKSRC0_HPLL_SHIFT (12) +#define S5PC100_CLKSRC0_AMMUX_MASK (0x1<<16) +#define S5PC100_CLKSRC0_AMMUX_SHIFT (16) +#define S5PC100_CLKSRC0_HREF_MASK (0x1<<20) +#define S5PC100_CLKSRC0_HREF_SHIFT (20) +#define S5PC1XX_CLKSRC0_ONENAND_MASK (0x1<<24) +#define S5PC1XX_CLKSRC0_ONENAND_SHIFT (24) + + +/* CLKSRC1 */ +#define S5PC100_CLKSRC1_UART_MASK (0x1<<0) +#define S5PC100_CLKSRC1_UART_SHIFT (0) +#define S5PC100_CLKSRC1_SPI0_MASK (0x3<<4) +#define S5PC100_CLKSRC1_SPI0_SHIFT (4) +#define S5PC100_CLKSRC1_SPI1_MASK (0x3<<8) +#define S5PC100_CLKSRC1_SPI1_SHIFT (8) +#define S5PC100_CLKSRC1_SPI2_MASK (0x3<<12) +#define S5PC100_CLKSRC1_SPI2_SHIFT (12) +#define S5PC100_CLKSRC1_IRDA_MASK (0x3<<16) +#define S5PC100_CLKSRC1_IRDA_SHIFT (16) +#define S5PC100_CLKSRC1_UHOST_MASK (0x3<<20) +#define S5PC100_CLKSRC1_UHOST_SHIFT (20) +#define S5PC100_CLKSRC1_CLK48M_MASK (0x1<<24) +#define S5PC100_CLKSRC1_CLK48M_SHIFT (24) + +/* CLKSRC2 */ +#define S5PC100_CLKSRC2_MMC0_MASK (0x3<<0) +#define S5PC100_CLKSRC2_MMC0_SHIFT (0) +#define S5PC100_CLKSRC2_MMC1_MASK (0x3<<4) +#define S5PC100_CLKSRC2_MMC1_SHIFT (4) +#define S5PC100_CLKSRC2_MMC2_MASK (0x3<<8) +#define S5PC100_CLKSRC2_MMC2_SHIFT (8) +#define S5PC100_CLKSRC2_LCD_MASK (0x3<<12) +#define S5PC100_CLKSRC2_LCD_SHIFT (12) +#define S5PC100_CLKSRC2_FIMC0_MASK (0x3<<16) +#define S5PC100_CLKSRC2_FIMC0_SHIFT (16) +#define S5PC100_CLKSRC2_FIMC1_MASK (0x3<<20) +#define S5PC100_CLKSRC2_FIMC1_SHIFT (20) +#define S5PC100_CLKSRC2_FIMC2_MASK (0x3<<24) +#define S5PC100_CLKSRC2_FIMC2_SHIFT (24) +#define S5PC100_CLKSRC2_MIXER_MASK (0x3<<28) +#define S5PC100_CLKSRC2_MIXER_SHIFT (28) + +/* CLKSRC3 */ +#define S5PC100_CLKSRC3_PWI_MASK (0x3<<0) +#define S5PC100_CLKSRC3_PWI_SHIFT (0) +#define S5PC100_CLKSRC3_HCLKD2_MASK (0x1<<4) +#define S5PC100_CLKSRC3_HCLKD2_SHIFT (4) +#define S5PC100_CLKSRC3_I2SD2_MASK (0x3<<8) +#define S5PC100_CLKSRC3_I2SD2_SHIFT (8) +#define S5PC100_CLKSRC3_AUDIO0_MASK (0x7<<12) +#define S5PC100_CLKSRC3_AUDIO0_SHIFT (12) +#define S5PC100_CLKSRC3_AUDIO1_MASK (0x7<<16) +#define S5PC100_CLKSRC3_AUDIO1_SHIFT (16) +#define S5PC100_CLKSRC3_AUDIO2_MASK (0x7<<20) +#define S5PC100_CLKSRC3_AUDIO2_SHIFT (20) +#define S5PC100_CLKSRC3_SPDIF_MASK (0x3<<24) +#define S5PC100_CLKSRC3_SPDIF_SHIFT (24) + + +/* CLKDIV0 */ +#define S5PC1XX_CLKDIV0_APLL_MASK (0x1<<0) +#define S5PC1XX_CLKDIV0_APLL_SHIFT (0) +#define S5PC100_CLKDIV0_ARM_MASK (0x7<<4) +#define S5PC100_CLKDIV0_ARM_SHIFT (4) +#define S5PC100_CLKDIV0_D0_MASK (0x7<<8) +#define S5PC100_CLKDIV0_D0_SHIFT (8) +#define S5PC100_CLKDIV0_PCLKD0_MASK (0x7<<12) +#define S5PC100_CLKDIV0_PCLKD0_SHIFT (12) +#define S5PC100_CLKDIV0_SECSS_MASK (0x7<<16) +#define S5PC100_CLKDIV0_SECSS_SHIFT (16) + +/* CLKDIV1 */ +#define S5PC100_CLKDIV1_AM_MASK (0x7<<0) +#define S5PC100_CLKDIV1_AM_SHIFT (0) +#define S5PC100_CLKDIV1_MPLL_MASK (0x3<<4) +#define S5PC100_CLKDIV1_MPLL_SHIFT (4) +#define S5PC100_CLKDIV1_MPLL2_MASK (0x1<<8) +#define S5PC100_CLKDIV1_MPLL2_SHIFT (8) +#define S5PC100_CLKDIV1_D1_MASK (0x7<<12) +#define S5PC100_CLKDIV1_D1_SHIFT (12) +#define S5PC100_CLKDIV1_PCLKD1_MASK (0x7<<16) +#define S5PC100_CLKDIV1_PCLKD1_SHIFT (16) +#define S5PC100_CLKDIV1_ONENAND_MASK (0x3<<20) +#define S5PC100_CLKDIV1_ONENAND_SHIFT (20) +#define S5PC100_CLKDIV1_CAM_MASK (0x1F<<24) +#define S5PC100_CLKDIV1_CAM_SHIFT (24) + +/* CLKDIV2 */ +#define S5PC100_CLKDIV2_UART_MASK (0x7<<0) +#define S5PC100_CLKDIV2_UART_SHIFT (0) +#define S5PC100_CLKDIV2_SPI0_MASK (0xf<<4) +#define S5PC100_CLKDIV2_SPI0_SHIFT (4) +#define S5PC100_CLKDIV2_SPI1_MASK (0xf<<8) +#define S5PC100_CLKDIV2_SPI1_SHIFT (8) +#define S5PC100_CLKDIV2_SPI2_MASK (0xf<<12) +#define S5PC100_CLKDIV2_SPI2_SHIFT (12) +#define S5PC100_CLKDIV2_IRDA_MASK (0xf<<16) +#define S5PC100_CLKDIV2_IRDA_SHIFT (16) +#define S5PC100_CLKDIV2_UHOST_MASK (0xf<<20) +#define S5PC100_CLKDIV2_UHOST_SHIFT (20) + +/* CLKDIV3 */ +#define S5PC100_CLKDIV3_MMC0_MASK (0xf<<0) +#define S5PC100_CLKDIV3_MMC0_SHIFT (0) +#define S5PC100_CLKDIV3_MMC1_MASK (0xf<<4) +#define S5PC100_CLKDIV3_MMC1_SHIFT (4) +#define S5PC100_CLKDIV3_MMC2_MASK (0xf<<8) +#define S5PC100_CLKDIV3_MMC2_SHIFT (8) +#define S5PC100_CLKDIV3_LCD_MASK (0xf<<12) +#define S5PC100_CLKDIV3_LCD_SHIFT (12) +#define S5PC100_CLKDIV3_FIMC0_MASK (0xf<<16) +#define S5PC100_CLKDIV3_FIMC0_SHIFT (16) +#define S5PC100_CLKDIV3_FIMC1_MASK (0xf<<20) +#define S5PC100_CLKDIV3_FIMC1_SHIFT (20) +#define S5PC100_CLKDIV3_FIMC2_MASK (0xf<<24) +#define S5PC100_CLKDIV3_FIMC2_SHIFT (24) +#define S5PC100_CLKDIV3_HDMI_MASK (0xf<<28) +#define S5PC100_CLKDIV3_HDMI_SHIFT (28) + +/* CLKDIV4 */ +#define S5PC100_CLKDIV4_PWI_MASK (0x7<<0) +#define S5PC100_CLKDIV4_PWI_SHIFT (0) +#define S5PC100_CLKDIV4_HCLKD2_MASK (0x7<<4) +#define S5PC100_CLKDIV4_HCLKD2_SHIFT (4) +#define S5PC100_CLKDIV4_I2SD2_MASK (0xf<<8) +#define S5PC100_CLKDIV4_I2SD2_SHIFT (8) +#define S5PC100_CLKDIV4_AUDIO0_MASK (0xf<<12) +#define S5PC100_CLKDIV4_AUDIO0_SHIFT (12) +#define S5PC100_CLKDIV4_AUDIO1_MASK (0xf<<16) +#define S5PC100_CLKDIV4_AUDIO1_SHIFT (16) +#define S5PC100_CLKDIV4_AUDIO2_MASK (0xf<<20) +#define S5PC100_CLKDIV4_AUDIO2_SHIFT (20) + + +/* HCLKD0/PCLKD0 Clock Gate 0 Registers */ +#define S5PC100_CLKGATE_D00_INTC (1<<0) +#define S5PC100_CLKGATE_D00_TZIC (1<<1) +#define S5PC100_CLKGATE_D00_CFCON (1<<2) +#define S5PC100_CLKGATE_D00_MDMA (1<<3) +#define S5PC100_CLKGATE_D00_G2D (1<<4) +#define S5PC100_CLKGATE_D00_SECSS (1<<5) +#define S5PC100_CLKGATE_D00_CSSYS (1<<6) + +/* HCLKD0/PCLKD0 Clock Gate 1 Registers */ +#define S5PC100_CLKGATE_D01_DMC (1<<0) +#define S5PC100_CLKGATE_D01_SROMC (1<<1) +#define S5PC100_CLKGATE_D01_ONENAND (1<<2) +#define S5PC100_CLKGATE_D01_NFCON (1<<3) +#define S5PC100_CLKGATE_D01_INTMEM (1<<4) +#define S5PC100_CLKGATE_D01_EBI (1<<5) + +/* PCLKD0 Clock Gate 2 Registers */ +#define S5PC100_CLKGATE_D02_SECKEY (1<<1) +#define S5PC100_CLKGATE_D02_SDM (1<<2) + +/* HCLKD1/PCLKD1 Clock Gate 0 Registers */ +#define S5PC100_CLKGATE_D10_PDMA0 (1<<0) +#define S5PC100_CLKGATE_D10_PDMA1 (1<<1) +#define S5PC100_CLKGATE_D10_USBHOST (1<<2) +#define S5PC100_CLKGATE_D10_USBOTG (1<<3) +#define S5PC100_CLKGATE_D10_MODEMIF (1<<4) +#define S5PC100_CLKGATE_D10_HSMMC0 (1<<5) +#define S5PC100_CLKGATE_D10_HSMMC1 (1<<6) +#define S5PC100_CLKGATE_D10_HSMMC2 (1<<7) + +/* HCLKD1/PCLKD1 Clock Gate 1 Registers */ +#define S5PC100_CLKGATE_D11_LCD (1<<0) +#define S5PC100_CLKGATE_D11_ROTATOR (1<<1) +#define S5PC100_CLKGATE_D11_FIMC0 (1<<2) +#define S5PC100_CLKGATE_D11_FIMC1 (1<<3) +#define S5PC100_CLKGATE_D11_FIMC2 (1<<4) +#define S5PC100_CLKGATE_D11_JPEG (1<<5) +#define S5PC100_CLKGATE_D11_DSI (1<<6) +#define S5PC100_CLKGATE_D11_CSI (1<<7) +#define S5PC100_CLKGATE_D11_G3D (1<<8) + +/* HCLKD1/PCLKD1 Clock Gate 2 Registers */ +#define S5PC100_CLKGATE_D12_TV (1<<0) +#define S5PC100_CLKGATE_D12_VP (1<<1) +#define S5PC100_CLKGATE_D12_MIXER (1<<2) +#define S5PC100_CLKGATE_D12_HDMI (1<<3) +#define S5PC100_CLKGATE_D12_MFC (1<<4) + +/* HCLKD1/PCLKD1 Clock Gate 3 Registers */ +#define S5PC100_CLKGATE_D13_CHIPID (1<<0) +#define S5PC100_CLKGATE_D13_GPIO (1<<1) +#define S5PC100_CLKGATE_D13_APC (1<<2) +#define S5PC100_CLKGATE_D13_IEC (1<<3) +#define S5PC100_CLKGATE_D13_PWM (1<<6) +#define S5PC100_CLKGATE_D13_SYSTIMER (1<<7) +#define S5PC100_CLKGATE_D13_WDT (1<<8) +#define S5PC100_CLKGATE_D13_RTC (1<<9) + +/* HCLKD1/PCLKD1 Clock Gate 4 Registers */ +#define S5PC100_CLKGATE_D14_UART0 (1<<0) +#define S5PC100_CLKGATE_D14_UART1 (1<<1) +#define S5PC100_CLKGATE_D14_UART2 (1<<2) +#define S5PC100_CLKGATE_D14_UART3 (1<<3) +#define S5PC100_CLKGATE_D14_IIC (1<<4) +#define S5PC100_CLKGATE_D14_HDMI_IIC (1<<5) +#define S5PC100_CLKGATE_D14_SPI0 (1<<6) +#define S5PC100_CLKGATE_D14_SPI1 (1<<7) +#define S5PC100_CLKGATE_D14_SPI2 (1<<8) +#define S5PC100_CLKGATE_D14_IRDA (1<<9) +#define S5PC100_CLKGATE_D14_CCAN0 (1<<10) +#define S5PC100_CLKGATE_D14_CCAN1 (1<<11) +#define S5PC100_CLKGATE_D14_HSITX (1<<12) +#define S5PC100_CLKGATE_D14_HSIRX (1<<13) + +/* HCLKD1/PCLKD1 Clock Gate 5 Registers */ +#define S5PC100_CLKGATE_D15_IIS0 (1<<0) +#define S5PC100_CLKGATE_D15_IIS1 (1<<1) +#define S5PC100_CLKGATE_D15_IIS2 (1<<2) +#define S5PC100_CLKGATE_D15_AC97 (1<<3) +#define S5PC100_CLKGATE_D15_PCM0 (1<<4) +#define S5PC100_CLKGATE_D15_PCM1 (1<<5) +#define S5PC100_CLKGATE_D15_SPDIF (1<<6) +#define S5PC100_CLKGATE_D15_TSADC (1<<7) +#define S5PC100_CLKGATE_D15_KEYIF (1<<8) +#define S5PC100_CLKGATE_D15_CG (1<<9) + +/* HCLKD2 Clock Gate 0 Registers */ +#define S5PC100_CLKGATE_D20_HCLKD2 (1<<0) +#define S5PC100_CLKGATE_D20_I2SD2 (1<<1) + +/* Special Clock Gate 0 Registers */ +#define S5PC1XX_CLKGATE_SCLK0_HPM (1<<0) +#define S5PC1XX_CLKGATE_SCLK0_PWI (1<<1) +#define S5PC100_CLKGATE_SCLK0_ONENAND (1<<2) +#define S5PC100_CLKGATE_SCLK0_UART (1<<3) +#define S5PC100_CLKGATE_SCLK0_SPI0 (1<<4) +#define S5PC100_CLKGATE_SCLK0_SPI1 (1<<5) +#define S5PC100_CLKGATE_SCLK0_SPI2 (1<<6) +#define S5PC100_CLKGATE_SCLK0_SPI0_48 (1<<7) +#define S5PC100_CLKGATE_SCLK0_SPI1_48 (1<<8) +#define S5PC100_CLKGATE_SCLK0_SPI2_48 (1<<9) +#define S5PC100_CLKGATE_SCLK0_IRDA (1<<10) +#define S5PC100_CLKGATE_SCLK0_USBHOST (1<<11) +#define S5PC100_CLKGATE_SCLK0_MMC0 (1<<12) +#define S5PC100_CLKGATE_SCLK0_MMC1 (1<<13) +#define S5PC100_CLKGATE_SCLK0_MMC2 (1<<14) +#define S5PC100_CLKGATE_SCLK0_MMC0_48 (1<<15) +#define S5PC100_CLKGATE_SCLK0_MMC1_48 (1<<16) +#define S5PC100_CLKGATE_SCLK0_MMC2_48 (1<<17) + +/* Special Clock Gate 1 Registers */ +#define S5PC100_CLKGATE_SCLK1_LCD (1<<0) +#define S5PC100_CLKGATE_SCLK1_FIMC0 (1<<1) +#define S5PC100_CLKGATE_SCLK1_FIMC1 (1<<2) +#define S5PC100_CLKGATE_SCLK1_FIMC2 (1<<3) +#define S5PC100_CLKGATE_SCLK1_TV54 (1<<4) +#define S5PC100_CLKGATE_SCLK1_VDAC54 (1<<5) +#define S5PC100_CLKGATE_SCLK1_MIXER (1<<6) +#define S5PC100_CLKGATE_SCLK1_HDMI (1<<7) +#define S5PC100_CLKGATE_SCLK1_AUDIO0 (1<<8) +#define S5PC100_CLKGATE_SCLK1_AUDIO1 (1<<9) +#define S5PC100_CLKGATE_SCLK1_AUDIO2 (1<<10) +#define S5PC100_CLKGATE_SCLK1_SPDIF (1<<11) +#define S5PC100_CLKGATE_SCLK1_CAM (1<<12) + +/* register for power management */ +#define S5PC100_PWR_CFG S5PC1XX_CLKREG(0x8000) +#define S5PC100_EINT_WAKEUP_MASK S5PC1XX_CLKREG(0x8004) +#define S5PC100_NORMAL_CFG S5PC1XX_CLKREG(0x8010) +#define S5PC100_STOP_CFG S5PC1XX_CLKREG(0x8014) +#define S5PC100_SLEEP_CFG S5PC1XX_CLKREG(0x8018) +#define S5PC100_STOP_MEM_CFG S5PC1XX_CLKREG(0x801C) +#define S5PC100_OSC_FREQ S5PC1XX_CLKREG(0x8100) +#define S5PC100_OSC_STABLE S5PC1XX_CLKREG(0x8104) +#define S5PC100_PWR_STABLE S5PC1XX_CLKREG(0x8108) +#define S5PC100_MTC_STABLE S5PC1XX_CLKREG(0x8110) +#define S5PC100_CLAMP_STABLE S5PC1XX_CLKREG(0x8114) +#define S5PC100_OTHERS S5PC1XX_CLKREG(0x8200) +#define S5PC100_RST_STAT S5PC1XX_CLKREG(0x8300) +#define S5PC100_WAKEUP_STAT S5PC1XX_CLKREG(0x8304) +#define S5PC100_BLK_PWR_STAT S5PC1XX_CLKREG(0x8308) +#define S5PC100_INFORM0 S5PC1XX_CLKREG(0x8400) +#define S5PC100_INFORM1 S5PC1XX_CLKREG(0x8404) +#define S5PC100_INFORM2 S5PC1XX_CLKREG(0x8408) +#define S5PC100_INFORM3 S5PC1XX_CLKREG(0x840C) +#define S5PC100_INFORM4 S5PC1XX_CLKREG(0x8410) +#define S5PC100_INFORM5 S5PC1XX_CLKREG(0x8414) +#define S5PC100_INFORM6 S5PC1XX_CLKREG(0x8418) +#define S5PC100_INFORM7 S5PC1XX_CLKREG(0x841C) +#define S5PC100_DCGIDX_MAP0 S5PC1XX_CLKREG(0x8500) +#define S5PC100_DCGIDX_MAP1 S5PC1XX_CLKREG(0x8504) +#define S5PC100_DCGIDX_MAP2 S5PC1XX_CLKREG(0x8508) +#define S5PC100_DCGPERF_MAP0 S5PC1XX_CLKREG(0x850C) +#define S5PC100_DCGPERF_MAP1 S5PC1XX_CLKREG(0x8510) +#define S5PC100_DVCIDX_MAP S5PC1XX_CLKREG(0x8514) +#define S5PC100_FREQ_CPU S5PC1XX_CLKREG(0x8518) +#define S5PC100_FREQ_DPM S5PC1XX_CLKREG(0x851C) +#define S5PC100_DVSEMCLK_EN S5PC1XX_CLKREG(0x8520) +#define S5PC100_APLL_CON_L8 S5PC1XX_CLKREG(0x8600) +#define S5PC100_APLL_CON_L7 S5PC1XX_CLKREG(0x8604) +#define S5PC100_APLL_CON_L6 S5PC1XX_CLKREG(0x8608) +#define S5PC100_APLL_CON_L5 S5PC1XX_CLKREG(0x860C) +#define S5PC100_APLL_CON_L4 S5PC1XX_CLKREG(0x8610) +#define S5PC100_APLL_CON_L3 S5PC1XX_CLKREG(0x8614) +#define S5PC100_APLL_CON_L2 S5PC1XX_CLKREG(0x8618) +#define S5PC100_APLL_CON_L1 S5PC1XX_CLKREG(0x861C) +#define S5PC100_IEM_CONTROL S5PC1XX_CLKREG(0x8620) +#define S5PC100_CLKDIV_IEM_L8 S5PC1XX_CLKREG(0x8700) +#define S5PC100_CLKDIV_IEM_L7 S5PC1XX_CLKREG(0x8704) +#define S5PC100_CLKDIV_IEM_L6 S5PC1XX_CLKREG(0x8708) +#define S5PC100_CLKDIV_IEM_L5 S5PC1XX_CLKREG(0x870C) +#define S5PC100_CLKDIV_IEM_L4 S5PC1XX_CLKREG(0x8710) +#define S5PC100_CLKDIV_IEM_L3 S5PC1XX_CLKREG(0x8714) +#define S5PC100_CLKDIV_IEM_L2 S5PC1XX_CLKREG(0x8718) +#define S5PC100_CLKDIV_IEM_L1 S5PC1XX_CLKREG(0x871C) +#define S5PC100_IEM_HPMCLK_DIV S5PC1XX_CLKREG(0x8724) + +#define S5PC100_SWRESET S5PC1XX_CLKREG(0x100000) +#define S5PC100_OND_SWRESET S5PC1XX_CLKREG(0x100008) +#define S5PC100_GEN_CTRL S5PC1XX_CLKREG(0x100100) +#define S5PC100_GEN_STATUS S5PC1XX_CLKREG(0x100104) +#define S5PC100_MEM_SYS_CFG S5PC1XX_CLKREG(0x100200) +#define S5PC100_CAM_MUX_SEL S5PC1XX_CLKREG(0x100300) +#define S5PC100_MIXER_OUT_SEL S5PC1XX_CLKREG(0x100304) +#define S5PC100_LPMP_MODE_SEL S5PC1XX_CLKREG(0x100308) +#define S5PC100_MIPI_PHY_CON0 S5PC1XX_CLKREG(0x100400) +#define S5PC100_MIPI_PHY_CON1 S5PC1XX_CLKREG(0x100414) +#define S5PC100_HDMI_PHY_CON0 S5PC1XX_CLKREG(0x100420) + +#define S5PC100_CFG_WFI_CLEAN (~(3<<5)) +#define S5PC100_CFG_WFI_IDLE (1<<5) +#define S5PC100_CFG_WFI_STOP (2<<5) +#define S5PC100_CFG_WFI_SLEEP (3<<5) + +#define S5PC100_OTHER_SYS_INT 24 +#define S5PC100_OTHER_STA_TYPE 23 +#define STA_TYPE_EXPON 0 +#define STA_TYPE_SFR 1 + +#define S5PC100_PWR_STA_EXP_SCALE 0 +#define S5PC100_PWR_STA_CNT 4 + +#define S5PC100_PWR_STABLE_COUNT 85500 + +#define S5PC100_SLEEP_CFG_OSC_EN 0 + +/* OTHERS Resgister */ +#define S5PC100_OTHERS_USB_SIG_MASK (1 << 16) +#define S5PC100_OTHERS_MIPI_DPHY_EN (1 << 28) + +/* MIPI D-PHY Control Register 0 */ +#define S5PC100_MIPI_PHY_CON0_M_RESETN (1 << 1) +#define S5PC100_MIPI_PHY_CON0_S_RESETN (1 << 0) + +#endif /* _PLAT_REGS_CLOCK_H */ diff --git a/arch/arm/plat-s5pc1xx/include/plat/s5pc100.h b/arch/arm/plat-s5pc1xx/include/plat/s5pc100.h new file mode 100644 index 000000000000..45e275131665 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/include/plat/s5pc100.h @@ -0,0 +1,65 @@ +/* arch/arm/plat-s5pc1xx/include/plat/s5pc100.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Header file for s5pc100 cpu support + * + * Based on plat-s3c64xx/include/plat/s3c6400.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* Common init code for S5PC100 related SoCs */ +extern int s5pc100_init(void); +extern void s5pc100_map_io(void); +extern void s5pc100_init_clocks(int xtal); +extern int s5pc100_register_baseclocks(unsigned long xtal); +extern void s5pc100_init_irq(void); +extern void s5pc100_init_io(struct map_desc *mach_desc, int size); +extern void s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no); +extern void s5pc100_register_clocks(void); +extern void s5pc100_setup_clocks(void); +extern struct sysdev_class s5pc100_sysclass; + +#define s5pc100_init_uarts s5pc100_common_init_uarts + +/* Some day, belows will be moved to plat-s5pc/include/plat/cpu.h */ +extern void s5pc1xx_init_irq(u32 *vic_valid, int num); +extern void s5pc1xx_init_io(struct map_desc *mach_desc, int size); + +/* Some day, belows will be moved to plat-s5pc/include/plat/clock.h */ +extern struct clk clk_hpll; +extern struct clk clk_hd0; +extern struct clk clk_pd0; +extern struct clk clk_54m; +extern struct clk clk_dout_mpll2; +extern void s5pc1xx_register_clocks(void); +extern int s5pc1xx_sclk0_ctrl(struct clk *clk, int enable); +extern int s5pc1xx_sclk1_ctrl(struct clk *clk, int enable); + +/* Some day, belows will be moved to plat-s5pc/include/plat/devs.h */ +extern struct s3c24xx_uart_resources s5pc1xx_uart_resources[]; +extern struct platform_device s3c_device_g2d; +extern struct platform_device s3c_device_g3d; +extern struct platform_device s3c_device_vpp; +extern struct platform_device s3c_device_tvenc; +extern struct platform_device s3c_device_tvscaler; +extern struct platform_device s3c_device_rotator; +extern struct platform_device s3c_device_jpeg; +extern struct platform_device s3c_device_onenand; +extern struct platform_device s3c_device_usb_otghcd; +extern struct platform_device s3c_device_keypad; +extern struct platform_device s3c_device_ts; +extern struct platform_device s3c_device_g3d; +extern struct platform_device s3c_device_smc911x; +extern struct platform_device s3c_device_fimc0; +extern struct platform_device s3c_device_fimc1; +extern struct platform_device s3c_device_mfc; +extern struct platform_device s3c_device_ac97; +extern struct platform_device s3c_device_fimc0; +extern struct platform_device s3c_device_fimc1; +extern struct platform_device s3c_device_fimc2; + diff --git a/arch/arm/plat-s5pc1xx/irq.c b/arch/arm/plat-s5pc1xx/irq.c new file mode 100644 index 000000000000..80d6dd942cb8 --- /dev/null +++ b/arch/arm/plat-s5pc1xx/irq.c @@ -0,0 +1,259 @@ +/* arch/arm/plat-s5pc1xx/irq.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC1XX - Interrupt handling + * + * Based on plat-s3c64xx/irq.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/hardware/vic.h> + +#include <mach/map.h> +#include <plat/regs-timer.h> +#include <plat/cpu.h> + +/* Timer interrupt handling */ + +static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq) +{ + generic_handle_irq(sub_irq); +} + +static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER0); +} + +static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER1); +} + +static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER2); +} + +static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER3); +} + +static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc) +{ + s3c_irq_demux_timer(irq, IRQ_TIMER4); +} + +/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ + +static void s3c_irq_timer_mask(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; /* mask out pending interrupts */ + reg &= ~(1 << (irq - IRQ_TIMER0)); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static void s3c_irq_timer_unmask(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; /* mask out pending interrupts */ + reg |= 1 << (irq - IRQ_TIMER0); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static void s3c_irq_timer_ack(unsigned int irq) +{ + u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); + + reg &= 0x1f; + reg |= (1 << 5) << (irq - IRQ_TIMER0); + __raw_writel(reg, S3C64XX_TINT_CSTAT); +} + +static struct irq_chip s3c_irq_timer = { + .name = "s3c-timer", + .mask = s3c_irq_timer_mask, + .unmask = s3c_irq_timer_unmask, + .ack = s3c_irq_timer_ack, +}; + +struct uart_irq { + void __iomem *regs; + unsigned int base_irq; + unsigned int parent_irq; +}; + +/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] + * are consecutive when looking up the interrupt in the demux routines. + */ +static struct uart_irq uart_irqs[] = { + [0] = { + .regs = (void *)S3C_VA_UART0, + .base_irq = IRQ_S3CUART_BASE0, + .parent_irq = IRQ_UART0, + }, + [1] = { + .regs = (void *)S3C_VA_UART1, + .base_irq = IRQ_S3CUART_BASE1, + .parent_irq = IRQ_UART1, + }, + [2] = { + .regs = (void *)S3C_VA_UART2, + .base_irq = IRQ_S3CUART_BASE2, + .parent_irq = IRQ_UART2, + }, + [3] = { + .regs = (void *)S3C_VA_UART3, + .base_irq = IRQ_S3CUART_BASE3, + .parent_irq = IRQ_UART3, + }, +}; + +static inline void __iomem *s3c_irq_uart_base(unsigned int irq) +{ + struct uart_irq *uirq = get_irq_chip_data(irq); + return uirq->regs; +} + +static inline unsigned int s3c_irq_uart_bit(unsigned int irq) +{ + return irq & 3; +} + +/* UART interrupt registers, not worth adding to seperate include header */ +#define S3C64XX_UINTP 0x30 +#define S3C64XX_UINTSP 0x34 +#define S3C64XX_UINTM 0x38 + +static void s3c_irq_uart_mask(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg |= (1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); +} + +static void s3c_irq_uart_maskack(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg |= (1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); + __raw_writel(1 << bit, regs + S3C64XX_UINTP); +} + +static void s3c_irq_uart_unmask(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + u32 reg; + + reg = __raw_readl(regs + S3C64XX_UINTM); + reg &= ~(1 << bit); + __raw_writel(reg, regs + S3C64XX_UINTM); +} + +static void s3c_irq_uart_ack(unsigned int irq) +{ + void __iomem *regs = s3c_irq_uart_base(irq); + unsigned int bit = s3c_irq_uart_bit(irq); + + __raw_writel(1 << bit, regs + S3C64XX_UINTP); +} + +static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) +{ + struct uart_irq *uirq = &uart_irqs[irq - IRQ_UART0]; + u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); + int base = uirq->base_irq; + + if (pend & (1 << 0)) + generic_handle_irq(base); + if (pend & (1 << 1)) + generic_handle_irq(base + 1); + if (pend & (1 << 2)) + generic_handle_irq(base + 2); + if (pend & (1 << 3)) + generic_handle_irq(base + 3); +} + +static struct irq_chip s3c_irq_uart = { + .name = "s3c-uart", + .mask = s3c_irq_uart_mask, + .unmask = s3c_irq_uart_unmask, + .mask_ack = s3c_irq_uart_maskack, + .ack = s3c_irq_uart_ack, +}; + +static void __init s5pc1xx_uart_irq(struct uart_irq *uirq) +{ + void __iomem *reg_base = uirq->regs; + unsigned int irq; + int offs; + + /* mask all interrupts at the start. */ + __raw_writel(0xf, reg_base + S3C64XX_UINTM); + + for (offs = 0; offs < 3; offs++) { + irq = uirq->base_irq + offs; + + set_irq_chip(irq, &s3c_irq_uart); + set_irq_chip_data(irq, uirq); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); +} + +void __init s5pc1xx_init_irq(u32 *vic_valid, int num) +{ + int i; + int uart, irq; + + printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); + + /* initialise the pair of VICs */ + for (i = 0; i < num; i++) + vic_init((void *)S5PC1XX_VA_VIC(i), S3C_IRQ(i * S3C_IRQ_OFFSET), + vic_valid[i], 0); + + /* add the timer sub-irqs */ + + set_irq_chained_handler(IRQ_TIMER0, s3c_irq_demux_timer0); + set_irq_chained_handler(IRQ_TIMER1, s3c_irq_demux_timer1); + set_irq_chained_handler(IRQ_TIMER2, s3c_irq_demux_timer2); + set_irq_chained_handler(IRQ_TIMER3, s3c_irq_demux_timer3); + set_irq_chained_handler(IRQ_TIMER4, s3c_irq_demux_timer4); + + for (irq = IRQ_TIMER0; irq <= IRQ_TIMER4; irq++) { + set_irq_chip(irq, &s3c_irq_timer); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + + for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++) + s5pc1xx_uart_irq(&uart_irqs[uart]); +} + + diff --git a/arch/arm/plat-s5pc1xx/s5pc100-clock.c b/arch/arm/plat-s5pc1xx/s5pc100-clock.c new file mode 100644 index 000000000000..6b24035172fa --- /dev/null +++ b/arch/arm/plat-s5pc1xx/s5pc100-clock.c @@ -0,0 +1,1139 @@ +/* linux/arch/arm/plat-s5pc1xx/s5pc100-clock.c + * + * Copyright 2009 Samsung Electronics, Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 based common clock support + * + * Based on plat-s3c64xx/s3c6400-clock.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/sysdev.h> +#include <linux/io.h> + +#include <mach/hardware.h> +#include <mach/map.h> + +#include <plat/cpu-freq.h> + +#include <plat/regs-clock.h> +#include <plat/clock.h> +#include <plat/cpu.h> +#include <plat/pll.h> +#include <plat/devs.h> +#include <plat/s5pc100.h> + +/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call + * ext_xtal_mux for want of an actual name from the manual. +*/ + +static struct clk clk_ext_xtal_mux = { + .name = "ext_xtal", + .id = -1, +}; + +#define clk_fin_apll clk_ext_xtal_mux +#define clk_fin_mpll clk_ext_xtal_mux +#define clk_fin_epll clk_ext_xtal_mux +#define clk_fin_hpll clk_ext_xtal_mux + +#define clk_fout_mpll clk_mpll + +struct clk_sources { + unsigned int nr_sources; + struct clk **sources; +}; + +struct clksrc_clk { + struct clk clk; + unsigned int mask; + unsigned int shift; + + struct clk_sources *sources; + + unsigned int divider_shift; + void __iomem *reg_divider; + void __iomem *reg_source; +}; + +static int clk_default_setrate(struct clk *clk, unsigned long rate) +{ + clk->rate = rate; + return 1; +} + +struct clk clk_27m = { + .name = "clk_27m", + .id = -1, + .rate = 27000000, +}; + +static int clk_48m_ctrl(struct clk *clk, int enable) +{ + unsigned long flags; + u32 val; + + /* can't rely on clock lock, this register has other usages */ + local_irq_save(flags); + + val = __raw_readl(S5PC1XX_CLK_SRC1); + if (enable) + val |= S5PC100_CLKSRC1_CLK48M_MASK; + else + val &= ~S5PC100_CLKSRC1_CLK48M_MASK; + + __raw_writel(val, S5PC1XX_CLK_SRC1); + local_irq_restore(flags); + + return 0; +} + +struct clk clk_48m = { + .name = "clk_48m", + .id = -1, + .rate = 48000000, + .enable = clk_48m_ctrl, +}; + +struct clk clk_54m = { + .name = "clk_54m", + .id = -1, + .rate = 54000000, +}; + +struct clk clk_hpll = { + .name = "hpll", + .id = -1, +}; + +struct clk clk_hd0 = { + .name = "hclkd0", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, + .set_rate = clk_default_setrate, +}; + +struct clk clk_pd0 = { + .name = "pclkd0", + .id = -1, + .rate = 0, + .parent = NULL, + .ctrlbit = 0, + .set_rate = clk_default_setrate, +}; + +static int s5pc1xx_clk_gate(void __iomem *reg, + struct clk *clk, + int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + u32 con; + + con = __raw_readl(reg); + + if (enable) + con |= ctrlbit; + else + con &= ~ctrlbit; + + __raw_writel(con, reg); + return 0; +} + +static int s5pc1xx_clk_d00_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D00, clk, enable); +} + +static int s5pc1xx_clk_d01_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D01, clk, enable); +} + +static int s5pc1xx_clk_d02_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D02, clk, enable); +} + +static int s5pc1xx_clk_d10_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D10, clk, enable); +} + +static int s5pc1xx_clk_d11_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D11, clk, enable); +} + +static int s5pc1xx_clk_d12_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D12, clk, enable); +} + +static int s5pc1xx_clk_d13_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D13, clk, enable); +} + +static int s5pc1xx_clk_d14_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D14, clk, enable); +} + +static int s5pc1xx_clk_d15_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D15, clk, enable); +} + +static int s5pc1xx_clk_d20_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_CLKGATE_D20, clk, enable); +} + +int s5pc1xx_sclk0_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_SCLKGATE0, clk, enable); +} + +int s5pc1xx_sclk1_ctrl(struct clk *clk, int enable) +{ + return s5pc1xx_clk_gate(S5PC100_SCLKGATE1, clk, enable); +} + +static struct clk init_clocks_disable[] = { + { + .name = "dsi", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_DSI, + }, { + .name = "csi", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_CSI, + }, { + .name = "ccan0", + .id = 0, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_CCAN0, + }, { + .name = "ccan1", + .id = 1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_CCAN1, + }, { + .name = "keypad", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_KEYIF, + }, { + .name = "hclkd2", + .id = -1, + .parent = NULL, + .enable = s5pc1xx_clk_d20_ctrl, + .ctrlbit = S5PC100_CLKGATE_D20_HCLKD2, + }, { + .name = "iis-d2", + .id = -1, + .parent = NULL, + .enable = s5pc1xx_clk_d20_ctrl, + .ctrlbit = S5PC100_CLKGATE_D20_I2SD2, + }, { + .name = "otg", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_USBOTG, + }, +}; + +static struct clk init_clocks[] = { + /* System1 (D0_0) devices */ + { + .name = "intc", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d00_ctrl, + .ctrlbit = S5PC100_CLKGATE_D00_INTC, + }, { + .name = "tzic", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d00_ctrl, + .ctrlbit = S5PC100_CLKGATE_D00_TZIC, + }, { + .name = "cf-ata", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d00_ctrl, + .ctrlbit = S5PC100_CLKGATE_D00_CFCON, + }, { + .name = "mdma", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d00_ctrl, + .ctrlbit = S5PC100_CLKGATE_D00_MDMA, + }, { + .name = "g2d", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d00_ctrl, + .ctrlbit = S5PC100_CLKGATE_D00_G2D, + }, { + .name = "secss", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d00_ctrl, + .ctrlbit = S5PC100_CLKGATE_D00_SECSS, + }, { + .name = "cssys", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d00_ctrl, + .ctrlbit = S5PC100_CLKGATE_D00_CSSYS, + }, + + /* Memory (D0_1) devices */ + { + .name = "dmc", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d01_ctrl, + .ctrlbit = S5PC100_CLKGATE_D01_DMC, + }, { + .name = "sromc", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d01_ctrl, + .ctrlbit = S5PC100_CLKGATE_D01_SROMC, + }, { + .name = "onenand", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d01_ctrl, + .ctrlbit = S5PC100_CLKGATE_D01_ONENAND, + }, { + .name = "nand", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d01_ctrl, + .ctrlbit = S5PC100_CLKGATE_D01_NFCON, + }, { + .name = "intmem", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d01_ctrl, + .ctrlbit = S5PC100_CLKGATE_D01_INTMEM, + }, { + .name = "ebi", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d01_ctrl, + .ctrlbit = S5PC100_CLKGATE_D01_EBI, + }, + + /* System2 (D0_2) devices */ + { + .name = "seckey", + .id = -1, + .parent = &clk_pd0, + .enable = s5pc1xx_clk_d02_ctrl, + .ctrlbit = S5PC100_CLKGATE_D02_SECKEY, + }, { + .name = "sdm", + .id = -1, + .parent = &clk_hd0, + .enable = s5pc1xx_clk_d02_ctrl, + .ctrlbit = S5PC100_CLKGATE_D02_SDM, + }, + + /* File (D1_0) devices */ + { + .name = "pdma0", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_PDMA0, + }, { + .name = "pdma1", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_PDMA1, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_USBHOST, + }, { + .name = "modem", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_MODEMIF, + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_HSMMC0, + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_HSMMC1, + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_h, + .enable = s5pc1xx_clk_d10_ctrl, + .ctrlbit = S5PC100_CLKGATE_D10_HSMMC2, + }, + + /* Multimedia1 (D1_1) devices */ + { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_LCD, + }, { + .name = "rotator", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_ROTATOR, + }, { + .name = "fimc", + .id = 0, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_FIMC0, + }, { + .name = "fimc", + .id = 1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_FIMC1, + }, { + .name = "fimc", + .id = 2, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_FIMC2, + }, { + .name = "jpeg", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_JPEG, + }, { + .name = "g3d", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d11_ctrl, + .ctrlbit = S5PC100_CLKGATE_D11_G3D, + }, + + /* Multimedia2 (D1_2) devices */ + { + .name = "tv", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d12_ctrl, + .ctrlbit = S5PC100_CLKGATE_D12_TV, + }, { + .name = "vp", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d12_ctrl, + .ctrlbit = S5PC100_CLKGATE_D12_VP, + }, { + .name = "mixer", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d12_ctrl, + .ctrlbit = S5PC100_CLKGATE_D12_MIXER, + }, { + .name = "hdmi", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d12_ctrl, + .ctrlbit = S5PC100_CLKGATE_D12_HDMI, + }, { + .name = "mfc", + .id = -1, + .parent = &clk_h, + .enable = s5pc1xx_clk_d12_ctrl, + .ctrlbit = S5PC100_CLKGATE_D12_MFC, + }, + + /* System (D1_3) devices */ + { + .name = "chipid", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_CHIPID, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_GPIO, + }, { + .name = "apc", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_APC, + }, { + .name = "iec", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_IEC, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_PWM, + }, { + .name = "systimer", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_SYSTIMER, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_WDT, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d13_ctrl, + .ctrlbit = S5PC100_CLKGATE_D13_RTC, + }, + + /* Connectivity (D1_4) devices */ + { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_UART2, + }, { + .name = "uart", + .id = 3, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_UART3, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_IIC, + }, { + .name = "hdmi-i2c", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_HDMI_IIC, + }, { + .name = "spi", + .id = 0, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_SPI0, + }, { + .name = "spi", + .id = 1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_SPI1, + }, { + .name = "spi", + .id = 2, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_SPI2, + }, { + .name = "irda", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_IRDA, + }, { + .name = "hsitx", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_HSITX, + }, { + .name = "hsirx", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d14_ctrl, + .ctrlbit = S5PC100_CLKGATE_D14_HSIRX, + }, + + /* Audio (D1_5) devices */ + { + .name = "iis", + .id = 0, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_IIS0, + }, { + .name = "iis", + .id = 1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_IIS1, + }, { + .name = "iis", + .id = 2, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_IIS2, + }, { + .name = "ac97", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_AC97, + }, { + .name = "pcm", + .id = 0, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_PCM0, + }, { + .name = "pcm", + .id = 1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_PCM1, + }, { + .name = "spdif", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_SPDIF, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_TSADC, + }, { + .name = "keyif", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_KEYIF, + }, { + .name = "cg", + .id = -1, + .parent = &clk_p, + .enable = s5pc1xx_clk_d15_ctrl, + .ctrlbit = S5PC100_CLKGATE_D15_CG, + }, + + /* Audio (D2_0) devices: all disabled */ + + /* Special Clocks 1 */ + { + .name = "sclk_hpm", + .id = -1, + .parent = NULL, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC1XX_CLKGATE_SCLK0_HPM, + }, { + .name = "sclk_onenand", + .id = -1, + .parent = NULL, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK0_ONENAND, + }, { + .name = "sclk_spi_48", + .id = 0, + .parent = &clk_48m, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK0_SPI0_48, + }, { + .name = "sclk_spi_48", + .id = 1, + .parent = &clk_48m, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK0_SPI1_48, + }, { + .name = "sclk_spi_48", + .id = 2, + .parent = &clk_48m, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK0_SPI2_48, + }, { + .name = "sclk_mmc_48", + .id = 0, + .parent = &clk_48m, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK0_MMC0_48, + }, { + .name = "sclk_mmc_48", + .id = 1, + .parent = &clk_48m, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK0_MMC1_48, + }, { + .name = "sclk_mmc_48", + .id = 2, + .parent = &clk_48m, + .enable = s5pc1xx_sclk0_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK0_MMC2_48, + }, + + /* Special Clocks 2 */ + { + .name = "sclk_tv_54", + .id = -1, + .parent = &clk_54m, + .enable = s5pc1xx_sclk1_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK1_TV54, + }, { + .name = "sclk_vdac_54", + .id = -1, + .parent = &clk_54m, + .enable = s5pc1xx_sclk1_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK1_VDAC54, + }, { + .name = "sclk_spdif", + .id = -1, + .parent = NULL, + .enable = s5pc1xx_sclk1_ctrl, + .ctrlbit = S5PC100_CLKGATE_SCLK1_SPDIF, + }, +}; + +void __init s5pc1xx_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} +static struct clk clk_fout_apll = { + .name = "fout_apll", + .id = -1, +}; + +static struct clk *clk_src_apll_list[] = { + [0] = &clk_fin_apll, + [1] = &clk_fout_apll, +}; + +static struct clk_sources clk_src_apll = { + .sources = clk_src_apll_list, + .nr_sources = ARRAY_SIZE(clk_src_apll_list), +}; + +static struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .shift = S5PC1XX_CLKSRC0_APLL_SHIFT, + .mask = S5PC1XX_CLKSRC0_APLL_MASK, + .sources = &clk_src_apll, + .reg_source = S5PC1XX_CLK_SRC0, +}; + +static struct clk clk_fout_epll = { + .name = "fout_epll", + .id = -1, +}; + +static struct clk *clk_src_epll_list[] = { + [0] = &clk_fin_epll, + [1] = &clk_fout_epll, +}; + +static struct clk_sources clk_src_epll = { + .sources = clk_src_epll_list, + .nr_sources = ARRAY_SIZE(clk_src_epll_list), +}; + +static struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .shift = S5PC1XX_CLKSRC0_EPLL_SHIFT, + .mask = S5PC1XX_CLKSRC0_EPLL_MASK, + .sources = &clk_src_epll, + .reg_source = S5PC1XX_CLK_SRC0, +}; + +static struct clk *clk_src_mpll_list[] = { + [0] = &clk_fin_mpll, + [1] = &clk_fout_mpll, +}; + +static struct clk_sources clk_src_mpll = { + .sources = clk_src_mpll_list, + .nr_sources = ARRAY_SIZE(clk_src_mpll_list), +}; + +static struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .shift = S5PC1XX_CLKSRC0_MPLL_SHIFT, + .mask = S5PC1XX_CLKSRC0_MPLL_MASK, + .sources = &clk_src_mpll, + .reg_source = S5PC1XX_CLK_SRC0, +}; + +static unsigned long s5pc1xx_clk_doutmpll_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + unsigned long clkdiv; + + printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate); + + clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL_MASK; + rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL_SHIFT) + 1; + + return rate; +} + +static struct clk clk_dout_mpll = { + .name = "dout_mpll", + .id = -1, + .parent = &clk_mout_mpll.clk, + .get_rate = s5pc1xx_clk_doutmpll_get_rate, +}; + +static unsigned long s5pc1xx_clk_doutmpll2_get_rate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + unsigned long clkdiv; + + printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate); + + clkdiv = __raw_readl(S5PC1XX_CLK_DIV1) & S5PC100_CLKDIV1_MPLL2_MASK; + rate /= (clkdiv >> S5PC100_CLKDIV1_MPLL2_SHIFT) + 1; + + return rate; +} + +struct clk clk_dout_mpll2 = { + .name = "dout_mpll2", + .id = -1, + .parent = &clk_mout_mpll.clk, + .get_rate = s5pc1xx_clk_doutmpll2_get_rate, +}; + +static struct clk *clkset_uart_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll, + NULL, + NULL +}; + +static struct clk_sources clkset_uart = { + .sources = clkset_uart_list, + .nr_sources = ARRAY_SIZE(clkset_uart_list), +}; + +static inline struct clksrc_clk *to_clksrc(struct clk *clk) +{ + return container_of(clk, struct clksrc_clk, clk); +} + +static unsigned long s5pc1xx_getrate_clksrc(struct clk *clk) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + unsigned long rate = clk_get_rate(clk->parent); + u32 clkdiv = __raw_readl(sclk->reg_divider); + + clkdiv >>= sclk->divider_shift; + clkdiv &= 0xf; + clkdiv++; + + rate /= clkdiv; + return rate; +} + +static int s5pc1xx_setrate_clksrc(struct clk *clk, unsigned long rate) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + void __iomem *reg = sclk->reg_divider; + unsigned int div; + u32 val; + + rate = clk_round_rate(clk, rate); + div = clk_get_rate(clk->parent) / rate; + if (div > 16) + return -EINVAL; + + val = __raw_readl(reg); + val &= ~(0xf << sclk->shift); + val |= (div - 1) << sclk->shift; + __raw_writel(val, reg); + + return 0; +} + +static int s5pc1xx_setparent_clksrc(struct clk *clk, struct clk *parent) +{ + struct clksrc_clk *sclk = to_clksrc(clk); + struct clk_sources *srcs = sclk->sources; + u32 clksrc = __raw_readl(sclk->reg_source); + int src_nr = -1; + int ptr; + + for (ptr = 0; ptr < srcs->nr_sources; ptr++) + if (srcs->sources[ptr] == parent) { + src_nr = ptr; + break; + } + + if (src_nr >= 0) { + clksrc &= ~sclk->mask; + clksrc |= src_nr << sclk->shift; + + __raw_writel(clksrc, sclk->reg_source); + return 0; + } + + return -EINVAL; +} + +static unsigned long s5pc1xx_roundrate_clksrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + rate = parent_rate; + else { + div = rate / parent_rate; + + if (div == 0) + div = 1; + if (div > 16) + div = 16; + + rate = parent_rate / div; + } + + return rate; +} + +static struct clksrc_clk clk_uart_uclk1 = { + .clk = { + .name = "uclk1", + .id = -1, + .ctrlbit = S5PC100_CLKGATE_SCLK0_UART, + .enable = s5pc1xx_sclk0_ctrl, + .set_parent = s5pc1xx_setparent_clksrc, + .get_rate = s5pc1xx_getrate_clksrc, + .set_rate = s5pc1xx_setrate_clksrc, + .round_rate = s5pc1xx_roundrate_clksrc, + }, + .shift = S5PC100_CLKSRC1_UART_SHIFT, + .mask = S5PC100_CLKSRC1_UART_MASK, + .sources = &clkset_uart, + .divider_shift = S5PC100_CLKDIV2_UART_SHIFT, + .reg_divider = S5PC1XX_CLK_DIV2, + .reg_source = S5PC1XX_CLK_SRC1, +}; + +/* Clock initialisation code */ + +static struct clksrc_clk *init_parents[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_uart_uclk1, +}; + +static void __init_or_cpufreq s5pc1xx_set_clksrc(struct clksrc_clk *clk) +{ + struct clk_sources *srcs = clk->sources; + u32 clksrc = __raw_readl(clk->reg_source); + + clksrc &= clk->mask; + clksrc >>= clk->shift; + + if (clksrc > srcs->nr_sources || !srcs->sources[clksrc]) { + printk(KERN_ERR "%s: bad source %d\n", + clk->clk.name, clksrc); + return; + } + + clk->clk.parent = srcs->sources[clksrc]; + + printk(KERN_INFO "%s: source is %s (%d), rate is %ld\n", + clk->clk.name, clk->clk.parent->name, clksrc, + clk_get_rate(&clk->clk)); +} + +#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) + +void __init_or_cpufreq s5pc100_setup_clocks(void) +{ + struct clk *xtal_clk; + unsigned long xtal; + unsigned long armclk; + unsigned long hclkd0; + unsigned long hclk; + unsigned long pclkd0; + unsigned long pclk; + unsigned long apll; + unsigned long mpll; + unsigned long hpll; + unsigned long epll; + unsigned int ptr; + u32 clkdiv0, clkdiv1; + + printk(KERN_DEBUG "%s: registering clocks\n", __func__); + + clkdiv0 = __raw_readl(S5PC1XX_CLK_DIV0); + clkdiv1 = __raw_readl(S5PC1XX_CLK_DIV1); + + printk(KERN_DEBUG "%s: clkdiv0 = %08x, clkdiv1 = %08x\n", + __func__, clkdiv0, clkdiv1); + + xtal_clk = clk_get(NULL, "xtal"); + BUG_ON(IS_ERR(xtal_clk)); + + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); + + apll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_APLL_CON)); + mpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_MPLL_CON)); + epll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC1XX_EPLL_CON)); + hpll = s5pc1xx_get_pll(xtal, __raw_readl(S5PC100_HPLL_CON)); + + printk(KERN_INFO "S5PC100: PLL settings, A=%ld, M=%ld, E=%ld, H=%ld\n", + apll, mpll, epll, hpll); + + armclk = apll / GET_DIV(clkdiv0, S5PC1XX_CLKDIV0_APLL); + armclk = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_ARM); + hclkd0 = armclk / GET_DIV(clkdiv0, S5PC100_CLKDIV0_D0); + pclkd0 = hclkd0 / GET_DIV(clkdiv0, S5PC100_CLKDIV0_PCLKD0); + hclk = mpll / GET_DIV(clkdiv1, S5PC100_CLKDIV1_D1); + pclk = hclk / GET_DIV(clkdiv1, S5PC100_CLKDIV1_PCLKD1); + + printk(KERN_INFO "S5PC100: ARMCLK=%ld, HCLKD0=%ld, PCLKD0=%ld, HCLK=%ld, PCLK=%ld\n", + armclk, hclkd0, pclkd0, hclk, pclk); + + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_apll.rate = apll; + + clk_h.rate = hclk; + clk_p.rate = pclk; + + for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++) + s5pc1xx_set_clksrc(init_parents[ptr]); +} + +static struct clk *clks[] __initdata = { + &clk_ext_xtal_mux, + &clk_mout_epll.clk, + &clk_fout_epll, + &clk_mout_mpll.clk, + &clk_dout_mpll, + &clk_uart_uclk1.clk, + &clk_ext, + &clk_epll, + &clk_27m, + &clk_48m, + &clk_54m, +}; + +void __init s5pc100_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { + clkp = clks[ptr]; + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + clk_mpll.parent = &clk_mout_mpll.clk; + clk_epll.parent = &clk_mout_epll.clk; +} diff --git a/arch/arm/plat-s5pc1xx/s5pc100-init.c b/arch/arm/plat-s5pc1xx/s5pc100-init.c new file mode 100644 index 000000000000..c58710884ceb --- /dev/null +++ b/arch/arm/plat-s5pc1xx/s5pc100-init.c @@ -0,0 +1,27 @@ +/* linux/arch/arm/plat-s5pc1xx/s5pc100-init.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * S5PC100 - CPU initialisation (common with other S5PC1XX chips) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> + +#include <plat/cpu.h> +#include <plat/devs.h> +#include <plat/s5pc100.h> + +/* uart registration process */ + +void __init s5pc100_common_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + /* The driver name is s3c6400-uart to reuse s3c6400_serial_drv */ + s3c24xx_init_uartdevs("s3c6400-uart", s5pc1xx_uart_resources, cfg, no); +} diff --git a/arch/arm/plat-s5pc1xx/setup-i2c0.c b/arch/arm/plat-s5pc1xx/setup-i2c0.c new file mode 100644 index 000000000000..3d00c025fffb --- /dev/null +++ b/arch/arm/plat-s5pc1xx/setup-i2c0.c @@ -0,0 +1,25 @@ +/* linux/arch/arm/plat-s5pc1xx/setup-i2c0.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Base S5PC1XX I2C bus 0 gpio configuration + * + * Based on plat-s3c64xx/setup-i2c0.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> + +struct platform_device; /* don't need the contents */ + +#include <plat/iic.h> + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + /* Pin configuration would be needed */ +} diff --git a/arch/arm/plat-s5pc1xx/setup-i2c1.c b/arch/arm/plat-s5pc1xx/setup-i2c1.c new file mode 100644 index 000000000000..c8f3ca42f51d --- /dev/null +++ b/arch/arm/plat-s5pc1xx/setup-i2c1.c @@ -0,0 +1,25 @@ +/* linux/arch/arm/plat-s3c64xx/setup-i2c1.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min <bhmin@samsung.com> + * + * Base S5PC1XX I2C bus 1 gpio configuration + * + * Based on plat-s3c64xx/setup-i2c1.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> + +struct platform_device; /* don't need the contents */ + +#include <plat/iic.h> + +void s3c_i2c1_cfg_gpio(struct platform_device *dev) +{ + /* Pin configuration would be needed */ +} diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index a2bed62aec21..4fa9903b83cf 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -42,6 +42,7 @@ ENTRY(vfp_null_entry) mov pc, lr ENDPROC(vfp_null_entry) + .align 2 .LCvfp: .word vfp_vector @@ -61,6 +62,7 @@ ENTRY(vfp_testing_entry) mov pc, r9 @ we have handled the fault ENDPROC(vfp_testing_entry) + .align 2 VFP_arch_address: .word VFP_arch diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index 1aeae38725dd..66dc2d03b7fc 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -209,40 +209,55 @@ ENDPROC(vfp_save_state) last_VFP_context_address: .word last_VFP_context -ENTRY(vfp_get_float) - add pc, pc, r0, lsl #3 + .macro tbl_branch, base, tmp, shift +#ifdef CONFIG_THUMB2_KERNEL + adr \tmp, 1f + add \tmp, \tmp, \base, lsl \shift + mov pc, \tmp +#else + add pc, pc, \base, lsl \shift mov r0, r0 +#endif +1: + .endm + +ENTRY(vfp_get_float) + tbl_branch r0, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mrc p10, 0, r0, c\dr, c0, 0 @ fmrs r0, s0 +1: mrc p10, 0, r0, c\dr, c0, 0 @ fmrs r0, s0 mov pc, lr - mrc p10, 0, r0, c\dr, c0, 4 @ fmrs r0, s1 + .org 1b + 8 +1: mrc p10, 0, r0, c\dr, c0, 4 @ fmrs r0, s1 mov pc, lr + .org 1b + 8 .endr ENDPROC(vfp_get_float) ENTRY(vfp_put_float) - add pc, pc, r1, lsl #3 - mov r0, r0 + tbl_branch r1, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mcr p10, 0, r0, c\dr, c0, 0 @ fmsr r0, s0 +1: mcr p10, 0, r0, c\dr, c0, 0 @ fmsr r0, s0 mov pc, lr - mcr p10, 0, r0, c\dr, c0, 4 @ fmsr r0, s1 + .org 1b + 8 +1: mcr p10, 0, r0, c\dr, c0, 4 @ fmsr r0, s1 mov pc, lr + .org 1b + 8 .endr ENDPROC(vfp_put_float) ENTRY(vfp_get_double) - add pc, pc, r0, lsl #3 - mov r0, r0 + tbl_branch r0, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - fmrrd r0, r1, d\dr +1: fmrrd r0, r1, d\dr mov pc, lr + .org 1b + 8 .endr #ifdef CONFIG_VFPv3 @ d16 - d31 registers .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mrrc p11, 3, r0, r1, c\dr @ fmrrd r0, r1, d\dr +1: mrrc p11, 3, r0, r1, c\dr @ fmrrd r0, r1, d\dr mov pc, lr + .org 1b + 8 .endr #endif @@ -253,17 +268,18 @@ ENTRY(vfp_get_double) ENDPROC(vfp_get_double) ENTRY(vfp_put_double) - add pc, pc, r2, lsl #3 - mov r0, r0 + tbl_branch r2, r3, #3 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - fmdrr d\dr, r0, r1 +1: fmdrr d\dr, r0, r1 mov pc, lr + .org 1b + 8 .endr #ifdef CONFIG_VFPv3 @ d16 - d31 registers .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 - mcrr p11, 3, r1, r2, c\dr @ fmdrr r1, r2, d\dr +1: mcrr p11, 3, r1, r2, c\dr @ fmdrr r1, r2, d\dr mov pc, lr + .org 1b + 8 .endr #endif ENDPROC(vfp_put_double) |