diff options
Diffstat (limited to 'arch/arm')
309 files changed, 8388 insertions, 3849 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d3f5674bece8..ababf41517d6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -63,6 +63,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST depends on GENERIC_CLOCKEVENTS default y if SMP +config KTIME_SCALAR + bool + default y + config HAVE_TCM bool select GENERIC_ALLOCATOR @@ -178,11 +182,6 @@ config FIQ config ARCH_MTD_XIP bool -config ARM_L1_CACHE_SHIFT_6 - bool - help - Setting ARM L1 cache line size to 64 Bytes. - config VECTORS_BASE hex default 0xffff0000 if MMU || CPU_HIGH_VECTOR @@ -346,7 +345,7 @@ config ARCH_FOOTBRIDGE bool "FootBridge" select CPU_SA110 select FOOTBRIDGE - select ARCH_USES_GETTIMEOFFSET + select GENERIC_CLOCKEVENTS help Support for systems based on the DC21285 companion chip ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. @@ -876,6 +875,16 @@ config PLAT_SPEAR help Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx). +config ARCH_VT8500 + bool "VIA/WonderMedia 85xx" + select CPU_ARM926T + select GENERIC_GPIO + select ARCH_HAS_CPUFREQ + select GENERIC_CLOCKEVENTS + select ARCH_REQUIRE_GPIOLIB + select HAVE_PWM + help + Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. endchoice # @@ -1008,6 +1017,8 @@ source "arch/arm/mach-versatile/Kconfig" source "arch/arm/mach-vexpress/Kconfig" +source "arch/arm/mach-vt8500/Kconfig" + source "arch/arm/mach-w90x900/Kconfig" # Definitions to make life easier @@ -1141,7 +1152,7 @@ config ARM_ERRATA_742231 config PL310_ERRATA_588369 bool "Clean & Invalidate maintenance operations do not invalidate clean lines" - depends on CACHE_L2X0 && ARCH_OMAP4 + depends on CACHE_L2X0 help The PL310 L2 cache controller implements three types of Clean & Invalidate maintenance operations: by Physical Address @@ -1150,8 +1161,7 @@ config PL310_ERRATA_588369 clean operation followed immediately by an invalidate operation, both performing to the same memory location. This functionality is not correctly implemented in PL310 as clean lines are not - invalidated as a result of these operations. Note that this errata - uses Texas Instrument's secure monitor api. + invalidated as a result of these operations. config ARM_ERRATA_720789 bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID" @@ -1165,6 +1175,17 @@ config ARM_ERRATA_720789 tables. The workaround changes the TLB flushing routines to invalidate entries regardless of the ASID. +config PL310_ERRATA_727915 + bool "Background Clean & Invalidate by Way operation can cause data corruption" + depends on CACHE_L2X0 + help + PL310 implements the Clean & Invalidate by Way L2 cache maintenance + operation (offset 0x7FC). This operation runs in background so that + PL310 can handle normal accesses while it is in progress. Under very + rare circumstances, due to this erratum, write data can be lost when + PL310 treats a cacheable write transaction during a Clean & + Invalidate by Way operation. + config ARM_ERRATA_743622 bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption" depends on CPU_V7 @@ -1178,6 +1199,53 @@ config ARM_ERRATA_743622 visible impact on the overall performance or power consumption of the processor. +config ARM_ERRATA_751472 + bool "ARM errata: Interrupted ICIALLUIS may prevent completion of broadcasted operation" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 751472 Cortex-A9 (prior + to r3p0) erratum. An interrupted ICIALLUIS operation may prevent the + completion of a following broadcasted operation if the second + operation is received by a CPU before the ICIALLUIS has completed, + potentially leading to corrupted entries in the cache or TLB. + +config ARM_ERRATA_753970 + bool "ARM errata: cache sync operation may be faulty" + depends on CACHE_PL310 + help + This option enables the workaround for the 753970 PL310 (r3p0) erratum. + + Under some condition the effect of cache sync operation on + the store buffer still remains when the operation completes. + This means that the store buffer is always asked to drain and + this prevents it from merging any further writes. The workaround + is to replace the normal offset of cache sync operation (0x730) + by another offset targeting an unmapped PL310 register 0x740. + This has the same effect as the cache sync operation: store buffer + drain and waiting for all buffers empty. + +config ARM_ERRATA_754322 + bool "ARM errata: possible faulty MMU translations following an ASID switch" + depends on CPU_V7 + help + This option enables the workaround for the 754322 Cortex-A9 (r2p*, + r3p*) erratum. A speculative memory access may cause a page table walk + which starts prior to an ASID switch but completes afterwards. This + can populate the micro-TLB with a stale entry which may be hit with + the new ASID. This workaround places two dsb instructions in the mm + switching code so that no page table walks can cross the ASID switch. + +config ARM_ERRATA_754327 + bool "ARM errata: no automatic Store Buffer drain" + depends on CPU_V7 && SMP + help + This option enables the workaround for the 754327 Cortex-A9 (prior to + r2p0) erratum. The Store Buffer does not have any automatic draining + mechanism and therefore a livelock may occur if an external agent + continuously polls a memory location waiting to observe an update. + This workaround defines cpu_relax() as smp_mb(), preventing correctly + written polling loops from denying visibility of updates to memory. + endmenu source "arch/arm/common/Kconfig" @@ -1373,6 +1441,37 @@ config THUMB2_KERNEL If unsure, say N. +config THUMB2_AVOID_R_ARM_THM_JUMP11 + bool "Work around buggy Thumb-2 short branch relocations in gas" + depends on THUMB2_KERNEL && MODULES + default y + help + Various binutils versions can resolve Thumb-2 branches to + locally-defined, preemptible global symbols as short-range "b.n" + branch instructions. + + This is a problem, because there's no guarantee the final + destination of the symbol, or any candidate locations for a + trampoline, are within range of the branch. For this reason, the + kernel does not support fixing up the R_ARM_THM_JUMP11 (102) + relocation in modules at all, and it makes little sense to add + support. + + The symptom is that the kernel fails with an "unsupported + relocation" error when loading some modules. + + Until fixed tools are available, passing + -fno-optimize-sibling-calls to gcc should prevent gcc generating + code which hits this problem, at the cost of a bit of extra runtime + stack usage in some cases. + + The problem is described in more detail at: + https://bugs.launchpad.net/binutils-linaro/+bug/725126 + + Only Thumb-2 kernels are affected. + + Unless you are sure your tools don't have this problem, say Y. + config ARM_ASM_UNIFIED bool @@ -1393,7 +1492,7 @@ config AEABI config OABI_COMPAT bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)" - depends on AEABI && EXPERIMENTAL + depends on AEABI && EXPERIMENTAL && !THUMB2_KERNEL default y help This option preserves the old syscall interface along with the @@ -1621,6 +1720,18 @@ config ZBOOT_ROM Say Y here if you intend to execute your compressed kernel image (zImage) directly from ROM or flash. If unsure, say N. +config ZBOOT_ROM_MMCIF + bool "Include MMCIF loader in zImage (EXPERIMENTAL)" + depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL + help + Say Y here to include experimental MMCIF loading code in the + ROM-able zImage. With this enabled it is possible to write the + the ROM-able zImage kernel image to an MMC card and boot the + kernel straight from the reset vector. At reset the processor + Mask ROM will load the first part of the the ROM-able zImage + which in turn loads the rest the kernel image to RAM using the + MMCIF hardware block. + config CMDLINE string "Default kernel command string" default "" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 9c430525e13e..1e20c414d5cf 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -15,7 +15,7 @@ ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 endif -OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S +OBJCOPYFLAGS :=-O binary -R .comment -S GZFLAGS :=-9 #KBUILD_CFLAGS +=-pipe # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: @@ -106,6 +106,10 @@ AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mau 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 +# Work around buggy relocation from gas if requested: +ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y) +CFLAGS_MODULE +=-fno-optimize-sibling-calls +endif endif # Need -Uarm for gcc < 3.x @@ -191,6 +195,7 @@ machine-$(CONFIG_ARCH_U300) := u300 machine-$(CONFIG_ARCH_U8500) := ux500 machine-$(CONFIG_ARCH_VERSATILE) := versatile machine-$(CONFIG_ARCH_VEXPRESS) := vexpress +machine-$(CONFIG_ARCH_VT8500) := vt8500 machine-$(CONFIG_ARCH_W90X900) := w90x900 machine-$(CONFIG_ARCH_NUC93X) := nuc93x machine-$(CONFIG_FOOTBRIDGE) := footbridge @@ -281,7 +286,7 @@ bzImage: zImage zImage Image xipImage bootpImage uImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@ -zinstall install: vmlinux +zinstall uinstall install: vmlinux $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@ # We use MRPROPER_FILES and CLEAN_FILES now @@ -302,6 +307,7 @@ define archhelp echo ' (supply initrd image via make variable INITRD=<path>)' echo ' install - Install uncompressed kernel' echo ' zinstall - Install compressed kernel' + echo ' uinstall - Install U-Boot wrapped compressed kernel' echo ' Install using (your) ~/bin/$(INSTALLKERNEL) or' echo ' (distribution) /sbin/$(INSTALLKERNEL) or' echo ' install to $$(INSTALL_PATH) and run lilo' diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile index 4d26f2c52a75..9128fddf1109 100644 --- a/arch/arm/boot/Makefile +++ b/arch/arm/boot/Makefile @@ -99,6 +99,10 @@ zinstall: $(obj)/zImage $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ $(obj)/zImage System.map "$(INSTALL_PATH)" +uinstall: $(obj)/uImage + $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ + $(obj)/uImage System.map "$(INSTALL_PATH)" + zi: $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ $(obj)/zImage System.map "$(INSTALL_PATH)" diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index ab204db594d3..c6028967d336 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -1,3 +1,7 @@ font.c -piggy.gz +lib1funcs.S +piggy.gzip +piggy.lzo +piggy.lzma +vmlinux vmlinux.lds diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 0a8f748e506a..f9f77c65dff3 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -4,9 +4,20 @@ # create a compressed vmlinuz image from the original vmlinux # +OBJS = + +# Ensure that mmcif loader code appears early in the image +# to minimise that number of bocks that have to be read in +# order to load it. +ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y) +ifeq ($(CONFIG_ARCH_SH7372),y) +OBJS += mmcif-sh7372.o +endif +endif + AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) HEAD = head.o -OBJS = misc.o decompress.o +OBJS += misc.o decompress.o FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c # @@ -29,6 +40,10 @@ ifeq ($(CONFIG_ARCH_SA1100),y) OBJS += head-sa1100.o endif +ifeq ($(CONFIG_ARCH_VT8500),y) +OBJS += head-vt8500.o +endif + ifeq ($(CONFIG_CPU_XSCALE),y) OBJS += head-xscale.o endif @@ -83,9 +98,11 @@ endif EXTRA_CFLAGS := -fpic -fno-builtin EXTRA_AFLAGS := -Wa,-march=all +# Provide size of uncompressed kernel to the decompressor via a linker symbol. +LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image) # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) -LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR) +LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) endif ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S index 30973b76e6ae..c943d2e7da9d 100644 --- a/arch/arm/boot/compressed/head-shmobile.S +++ b/arch/arm/boot/compressed/head-shmobile.S @@ -25,6 +25,36 @@ /* load board-specific initialization code */ #include <mach/zboot.h> +#ifdef CONFIG_ZBOOT_ROM_MMCIF + /* Load image from MMC */ + adr sp, __tmp_stack + 128 + ldr r0, __image_start + ldr r1, __image_end + subs r1, r1, r0 + ldr r0, __load_base + bl mmcif_loader + + /* Jump to loaded code */ + ldr r0, __loaded + ldr r1, __image_start + sub r0, r0, r1 + ldr r1, __load_base + add pc, r0, r1 + +__image_start: + .long _start +__image_end: + .long _got_end +__load_base: + .long CONFIG_MEMORY_START + 0x02000000 @ Load at 32Mb into SDRAM +__loaded: + .long __continue + .align +__tmp_stack: + .space 128 +__continue: +#endif /* CONFIG_ZBOOT_ROM_MMCIF */ + b 1f __atags:@ tag #1 .long 12 @ tag->hdr.size = tag_size(tag_core); diff --git a/arch/arm/boot/compressed/head-vt8500.S b/arch/arm/boot/compressed/head-vt8500.S new file mode 100644 index 000000000000..1dc1e21a3be3 --- /dev/null +++ b/arch/arm/boot/compressed/head-vt8500.S @@ -0,0 +1,46 @@ +/* + * linux/arch/arm/boot/compressed/head-vt8500.S + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * VIA VT8500 specific tweaks. This is merged into head.S by the linker. + * + */ + +#include <linux/linkage.h> +#include <asm/mach-types.h> + + .section ".start", "ax" + +__VT8500_start: + @ Compare the SCC ID register against a list of known values + ldr r1, .SCCID + ldr r3, [r1] + + @ VT8500 override + ldr r4, .VT8500SCC + cmp r3, r4 + ldreq r7, .ID_BV07 + beq .Lendvt8500 + + @ WM8505 override + ldr r4, .WM8505SCC + cmp r3, r4 + ldreq r7, .ID_8505 + beq .Lendvt8500 + + @ Otherwise, leave the bootloader's machine id untouched + +.SCCID: + .word 0xd8120000 +.VT8500SCC: + .word 0x34000102 +.WM8505SCC: + .word 0x34260103 + +.ID_BV07: + .word MACH_TYPE_BV07 +.ID_8505: + .word MACH_TYPE_WM8505_7IN_NETBOOK + +.Lendvt8500: diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 91f20f0b3044..84ac4d656310 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -128,14 +128,14 @@ wait: mrc p14, 0, pc, c0, c1, 0 .arm @ Always enter in ARM state start: .type start,#function - THUMB( adr r12, BSYM(1f) ) - THUMB( bx r12 ) - THUMB( .rept 6 ) - ARM( .rept 8 ) + .rept 7 mov r0, r0 .endr + ARM( mov r0, r0 ) + ARM( b 1f ) + THUMB( adr r12, BSYM(1f) ) + THUMB( bx r12 ) - b 1f .word 0x016f2818 @ Magic numbers to help the loader .word start @ absolute load/run zImage address .word _edata @ zImage end address @@ -174,9 +174,7 @@ not_angel: */ .text - adr r0, LC0 - ldmia r0, {r1, r2, r3, r5, r6, r11, ip} - ldr sp, [r0, #28] + #ifdef CONFIG_AUTO_ZRELADDR @ determine final kernel image address mov r4, pc @@ -185,35 +183,108 @@ not_angel: #else ldr r4, =zreladdr #endif - subs r0, r0, r1 @ calculate the delta offset - @ if delta is zero, we are - beq not_relocated @ running at the address we - @ were linked at. + bl cache_on + +restart: adr r0, LC0 + ldmia r0, {r1, r2, r3, r5, r6, r9, r11, r12} + ldr sp, [r0, #32] + + /* + * We might be running at a different address. We need + * to fix up various pointers. + */ + sub r0, r0, r1 @ calculate the delta offset + add r5, r5, r0 @ _start + add r6, r6, r0 @ _edata +#ifndef CONFIG_ZBOOT_ROM + /* malloc space is above the relocated stack (64k max) */ + add sp, sp, r0 + add r10, sp, #0x10000 +#else /* - * We're running at a different address. We need to fix - * up various pointers: - * r5 - zImage base address (_start) - * r6 - size of decompressed image - * r11 - GOT start - * ip - GOT end + * With ZBOOT_ROM the bss/stack is non relocatable, + * but someone could still run this code from RAM, + * in which case our reference is _edata. */ - add r5, r5, r0 + mov r10, r6 +#endif + +/* + * Check to see if we will overwrite ourselves. + * r4 = final kernel address + * r5 = start of this image + * r9 = size of decompressed image + * r10 = end of this image, including bss/stack/malloc space if non XIP + * We basically want: + * r4 >= r10 -> OK + * r4 + image length <= r5 -> OK + */ + cmp r4, r10 + bhs wont_overwrite + add r10, r4, r9 + cmp r10, r5 + bls wont_overwrite + +/* + * Relocate ourselves past the end of the decompressed kernel. + * r5 = start of this image + * r6 = _edata + * r10 = end of the decompressed kernel + * Because we always copy ahead, we need to do it from the end and go + * backward in case the source and destination overlap. + */ + /* Round up to next 256-byte boundary. */ + add r10, r10, #256 + bic r10, r10, #255 + + sub r9, r6, r5 @ size to copy + add r9, r9, #31 @ rounded up to a multiple + bic r9, r9, #31 @ ... of 32 bytes + add r6, r9, r5 + add r9, r9, r10 + +1: ldmdb r6!, {r0 - r3, r10 - r12, lr} + cmp r6, r5 + stmdb r9!, {r0 - r3, r10 - r12, lr} + bhi 1b + + /* Preserve offset to relocated code. */ + sub r6, r9, r6 + + bl cache_clean_flush + + adr r0, BSYM(restart) + add r0, r0, r6 + mov pc, r0 + +wont_overwrite: +/* + * If delta is zero, we are running at the address we were linked at. + * r0 = delta + * r2 = BSS start + * r3 = BSS end + * r4 = kernel execution address + * r7 = architecture ID + * r8 = atags pointer + * r11 = GOT start + * r12 = GOT end + * sp = stack pointer + */ + teq r0, #0 + beq not_relocated add r11, r11, r0 - add ip, ip, r0 + add r12, r12, r0 #ifndef CONFIG_ZBOOT_ROM /* * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, * we need to fix up pointers into the BSS region. - * r2 - BSS start - * r3 - BSS end - * sp - stack pointer + * Note that the stack pointer has already been fixed up. */ add r2, r2, r0 add r3, r3, r0 - add sp, sp, r0 /* * Relocate all entries in the GOT table. @@ -221,7 +292,7 @@ not_angel: 1: ldr r1, [r11, #0] @ relocate entries in the GOT add r1, r1, r0 @ table. This fixes up the str r1, [r11], #4 @ C references. - cmp r11, ip + cmp r11, r12 blo 1b #else @@ -234,7 +305,7 @@ not_angel: cmphs r3, r1 @ _end < entry addlo r1, r1, r0 @ table. This fixes up the str r1, [r11], #4 @ C references. - cmp r11, ip + cmp r11, r12 blo 1b #endif @@ -246,76 +317,24 @@ not_relocated: mov r0, #0 cmp r2, r3 blo 1b - /* - * The C runtime environment should now be setup - * sufficiently. Turn the cache on, set up some - * pointers, and start decompressing. - */ - bl cache_on - - mov r1, sp @ malloc space above stack - add r2, sp, #0x10000 @ 64k max - /* - * Check to see if we will overwrite ourselves. - * r4 = final kernel address - * r5 = start of this image - * r6 = size of decompressed image - * r2 = end of malloc space (and therefore this image) - * We basically want: - * r4 >= r2 -> OK - * r4 + image length <= r5 -> OK + * The C runtime environment should now be setup sufficiently. + * Set up some pointers, and start decompressing. + * r4 = kernel execution address + * r7 = architecture ID + * r8 = atags pointer */ - cmp r4, r2 - bhs wont_overwrite - add r0, r4, r6 - cmp r0, r5 - bls wont_overwrite - - mov r5, r2 @ decompress after malloc space - mov r0, r5 + mov r0, r4 + mov r1, sp @ malloc space above stack + add r2, sp, #0x10000 @ 64k max mov r3, r7 bl decompress_kernel - - add r0, r0, #127 + 128 @ alignment + stack - bic r0, r0, #127 @ align the kernel length -/* - * r0 = decompressed kernel length - * r1-r3 = unused - * r4 = kernel execution address - * r5 = decompressed kernel start - * r7 = architecture ID - * r8 = atags pointer - * 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 - 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 - mov sp, r1 - add sp, sp, #128 @ relocate the stack - bl cache_clean_flush - 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. - * - * r4 = kernel execution address - * r7 = architecture ID - */ -wont_overwrite: mov r0, r4 - mov r3, r7 - bl decompress_kernel - b call_kernel + bl cache_off + mov r0, #0 @ must be zero + mov r1, r7 @ restore architecture number + mov r2, r8 @ restore atags pointer + mov pc, r4 @ call kernel .align 2 .type LC0, #object @@ -323,11 +342,11 @@ LC0: .word LC0 @ r1 .word __bss_start @ r2 .word _end @ r3 .word _start @ r5 - .word _image_size @ r6 + .word _edata @ r6 + .word _image_size @ r9 .word _got_start @ r11 .word _got_end @ ip .word user_stack_end @ sp -LC1: .word reloc_end - reloc_start .size LC0, . - LC0 #ifdef CONFIG_ARCH_RPC @@ -353,7 +372,7 @@ params: ldr r0, =0x10000100 @ params_phys for RPC * On exit, * r0, r1, r2, r3, r9, r10, r12 corrupted * This routine must preserve: - * r4, r5, r6, r7, r8 + * r4, r7, r8 */ .align 5 cache_on: mov r3, #8 @ cache_on function @@ -551,43 +570,6 @@ __common_mmu_cache_on: #endif /* - * All code following this line is relocatable. It is relocated by - * the above code to the end of the decompressed kernel image and - * executed there. During this time, we have no stacks. - * - * r0 = decompressed kernel length - * r1-r3 = unused - * r4 = kernel execution address - * r5 = decompressed kernel start - * r7 = architecture ID - * r8 = atags pointer - * r9-r12,r14 = corrupted - */ - .align 5 -reloc_start: add r9, r5, r0 - sub r9, r9, #128 @ do not copy the stack - debug_reloc_start - mov r1, r4 -1: - .rept 4 - ldmia r5!, {r0, r2, r3, r10 - r12, r14} @ relocate kernel - stmia r1!, {r0, r2, r3, r10 - r12, r14} - .endr - - cmp r5, r9 - blo 1b - mov sp, r1 - add sp, sp, #128 @ relocate the stack - debug_reloc_end - -call_kernel: bl cache_clean_flush - bl cache_off - mov r0, #0 @ must be zero - mov r1, r7 @ restore architecture number - mov r2, r8 @ restore atags pointer - mov pc, r4 @ call kernel - -/* * Here follow the relocatable cache support functions for the * various processors. This is a generic hook for locating an * entry and jumping to an instruction at the specified offset @@ -791,7 +773,7 @@ proc_types: * On exit, * r0, r1, r2, r3, r9, r12 corrupted * This routine must preserve: - * r4, r6, r7 + * r4, r7, r8 */ .align 5 cache_off: mov r3, #12 @ cache_off function @@ -866,7 +848,7 @@ __armv3_mmu_cache_off: * On exit, * r1, r2, r3, r9, r10, r11, r12 corrupted * This routine must preserve: - * r0, r4, r5, r6, r7 + * r4, r6, r7, r8 */ .align 5 cache_clean_flush: @@ -1088,7 +1070,6 @@ memdump: mov r12, r0 #endif .ltorg -reloc_end: .align .section ".stack", "aw", %nobits diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c new file mode 100644 index 000000000000..e6180af241f6 --- /dev/null +++ b/arch/arm/boot/compressed/mmcif-sh7372.c @@ -0,0 +1,87 @@ +/* + * sh7372 MMCIF loader + * + * Copyright (C) 2010 Magnus Damm + * Copyright (C) 2010 Simon Horman + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/mmc/sh_mmcif.h> +#include <mach/mmcif.h> + +#define MMCIF_BASE (void __iomem *)0xe6bd0000 + +#define PORT84CR (void __iomem *)0xe6050054 +#define PORT85CR (void __iomem *)0xe6050055 +#define PORT86CR (void __iomem *)0xe6050056 +#define PORT87CR (void __iomem *)0xe6050057 +#define PORT88CR (void __iomem *)0xe6050058 +#define PORT89CR (void __iomem *)0xe6050059 +#define PORT90CR (void __iomem *)0xe605005a +#define PORT91CR (void __iomem *)0xe605005b +#define PORT92CR (void __iomem *)0xe605005c +#define PORT99CR (void __iomem *)0xe6050063 + +#define SMSTPCR3 (void __iomem *)0xe615013c + +/* SH7372 specific MMCIF loader + * + * loads the zImage from an MMC card starting from block 1. + * + * The image must be start with a vrl4 header and + * the zImage must start at offset 512 of the image. That is, + * at block 2 (=byte 1024) on the media + * + * Use the following line to write the vrl4 formated zImage + * to an MMC card + * # dd if=vrl4.out of=/dev/sdx bs=512 seek=1 + */ +asmlinkage void mmcif_loader(unsigned char *buf, unsigned long len) +{ + mmcif_init_progress(); + mmcif_update_progress(MMCIF_PROGRESS_ENTER); + + /* Initialise MMC + * registers: PORT84CR-PORT92CR + * (MMCD0_0-MMCD0_7,MMCCMD0 Control) + * value: 0x04 - select function 4 + */ + __raw_writeb(0x04, PORT84CR); + __raw_writeb(0x04, PORT85CR); + __raw_writeb(0x04, PORT86CR); + __raw_writeb(0x04, PORT87CR); + __raw_writeb(0x04, PORT88CR); + __raw_writeb(0x04, PORT89CR); + __raw_writeb(0x04, PORT90CR); + __raw_writeb(0x04, PORT91CR); + __raw_writeb(0x04, PORT92CR); + + /* Initialise MMC + * registers: PORT99CR (MMCCLK0 Control) + * value: 0x10 | 0x04 - enable output | select function 4 + */ + __raw_writeb(0x14, PORT99CR); + + /* Enable clock to MMC hardware block */ + __raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 12), SMSTPCR3); + + mmcif_update_progress(MMCIF_PROGRESS_INIT); + + /* setup MMCIF hardware */ + sh_mmcif_boot_init(MMCIF_BASE); + + mmcif_update_progress(MMCIF_PROGRESS_LOAD); + + /* load kernel via MMCIF interface */ + sh_mmcif_boot_do_read(MMCIF_BASE, 2, /* Kernel is at block 2 */ + (len + SH_MMCIF_BBS - 1) / SH_MMCIF_BBS, buf); + + + /* Disable clock to MMC hardware block */ + __raw_writel(__raw_readl(SMSTPCR3) & (1 << 12), SMSTPCR3); + + mmcif_update_progress(MMCIF_PROGRESS_DONE); +} diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in index 366a924019ac..5309909d7282 100644 --- a/arch/arm/boot/compressed/vmlinux.lds.in +++ b/arch/arm/boot/compressed/vmlinux.lds.in @@ -43,9 +43,6 @@ SECTIONS _etext = .; - /* Assume size of decompressed image is 4x the compressed image */ - _image_size = (_etext - _text) * 4; - _got_start = .; .got : { *(.got) } _got_end = .; diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 778655f0257a..ea5ee4d067f3 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -6,6 +6,8 @@ config ARM_VIC config ARM_VIC_NR int + default 4 if ARCH_S5PV210 + default 3 if ARCH_S5P6442 || ARCH_S5PC100 default 2 depends on ARM_VIC help diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 224377211151..cb6b041c39d2 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -44,6 +44,19 @@ struct gic_chip_data { void __iomem *cpu_base; }; +/* + * Supported arch specific GIC irq extension. + * Default make them NULL. + */ +struct irq_chip gic_arch_extn = { + .irq_ack = NULL, + .irq_mask = NULL, + .irq_unmask = NULL, + .irq_retrigger = NULL, + .irq_set_type = NULL, + .irq_set_wake = NULL, +}; + #ifndef MAX_GIC_NR #define MAX_GIC_NR 1 #endif @@ -74,6 +87,8 @@ static inline unsigned int gic_irq(struct irq_data *d) static void gic_ack_irq(struct irq_data *d) { spin_lock(&irq_controller_lock); + if (gic_arch_extn.irq_ack) + gic_arch_extn.irq_ack(d); writel(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); spin_unlock(&irq_controller_lock); } @@ -84,6 +99,8 @@ static void gic_mask_irq(struct irq_data *d) spin_lock(&irq_controller_lock); writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); + if (gic_arch_extn.irq_mask) + gic_arch_extn.irq_mask(d); spin_unlock(&irq_controller_lock); } @@ -92,6 +109,8 @@ static void gic_unmask_irq(struct irq_data *d) u32 mask = 1 << (d->irq % 32); spin_lock(&irq_controller_lock); + if (gic_arch_extn.irq_unmask) + gic_arch_extn.irq_unmask(d); writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); spin_unlock(&irq_controller_lock); } @@ -116,6 +135,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type) spin_lock(&irq_controller_lock); + if (gic_arch_extn.irq_set_type) + gic_arch_extn.irq_set_type(d, type); + val = readl(base + GIC_DIST_CONFIG + confoff); if (type == IRQ_TYPE_LEVEL_HIGH) val &= ~confmask; @@ -141,32 +163,54 @@ static int gic_set_type(struct irq_data *d, unsigned int type) return 0; } +static int gic_retrigger(struct irq_data *d) +{ + if (gic_arch_extn.irq_retrigger) + return gic_arch_extn.irq_retrigger(d); + + return -ENXIO; +} + #ifdef CONFIG_SMP -static int -gic_set_cpu(struct irq_data *d, const struct cpumask *mask_val, bool force) +static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, + bool force) { void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3); unsigned int shift = (d->irq % 4) * 8; unsigned int cpu = cpumask_first(mask_val); - u32 val; - struct irq_desc *desc; + u32 val, mask, bit; - spin_lock(&irq_controller_lock); - desc = irq_to_desc(d->irq); - if (desc == NULL) { - spin_unlock(&irq_controller_lock); + if (cpu >= 8) return -EINVAL; - } + + mask = 0xff << shift; + bit = 1 << (cpu + shift); + + spin_lock(&irq_controller_lock); d->node = cpu; - val = readl(reg) & ~(0xff << shift); - val |= 1 << (cpu + shift); - writel(val, reg); + val = readl(reg) & ~mask; + writel(val | bit, reg); spin_unlock(&irq_controller_lock); return 0; } #endif +#ifdef CONFIG_PM +static int gic_set_wake(struct irq_data *d, unsigned int on) +{ + int ret = -ENXIO; + + if (gic_arch_extn.irq_set_wake) + ret = gic_arch_extn.irq_set_wake(d, on); + + return ret; +} + +#else +#define gic_set_wake NULL +#endif + static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) { struct gic_chip_data *chip_data = get_irq_data(irq); @@ -202,9 +246,11 @@ static struct irq_chip gic_chip = { .irq_mask = gic_mask_irq, .irq_unmask = gic_unmask_irq, .irq_set_type = gic_set_type, + .irq_retrigger = gic_retrigger, #ifdef CONFIG_SMP - .irq_set_affinity = gic_set_cpu, + .irq_set_affinity = gic_set_affinity, #endif + .irq_set_wake = gic_set_wake, }; void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) diff --git a/arch/arm/include/asm/a.out-core.h b/arch/arm/include/asm/a.out-core.h index 93d04acaa31f..92f10cb5c70c 100644 --- a/arch/arm/include/asm/a.out-core.h +++ b/arch/arm/include/asm/a.out-core.h @@ -32,11 +32,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT; dump->u_ssize = 0; - dump->u_debugreg[0] = tsk->thread.debug.bp[0].address; - dump->u_debugreg[1] = tsk->thread.debug.bp[1].address; - dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn.arm; - dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn.arm; - dump->u_debugreg[4] = tsk->thread.debug.nsaved; + memset(dump->u_debugreg, 0, sizeof(dump->u_debugreg)); if (dump->start_stack < 0x04000000) dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT; diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index d9b4c42d62ff..d5d8d5c72682 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -12,7 +12,7 @@ #include <linux/mm.h> -#include <asm/glue.h> +#include <asm/glue-cache.h> #include <asm/shmparam.h> #include <asm/cachetype.h> #include <asm/outercache.h> @@ -20,123 +20,6 @@ #define CACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) /* - * Cache Model - * =========== - */ -#undef _CACHE -#undef MULTI_CACHE - -#if defined(CONFIG_CPU_CACHE_V3) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v3 -# endif -#endif - -#if defined(CONFIG_CPU_CACHE_V4) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v4 -# endif -#endif - -#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ - defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \ - defined(CONFIG_CPU_ARM1026) -# define MULTI_CACHE 1 -#endif - -#if defined(CONFIG_CPU_FA526) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE fa -# endif -#endif - -#if defined(CONFIG_CPU_ARM926T) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE arm926 -# endif -#endif - -#if defined(CONFIG_CPU_ARM940T) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE arm940 -# endif -#endif - -#if defined(CONFIG_CPU_ARM946E) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE arm946 -# endif -#endif - -#if defined(CONFIG_CPU_CACHE_V4WB) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v4wb -# endif -#endif - -#if defined(CONFIG_CPU_XSCALE) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE xscale -# endif -#endif - -#if defined(CONFIG_CPU_XSC3) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE xsc3 -# endif -#endif - -#if defined(CONFIG_CPU_MOHAWK) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE mohawk -# endif -#endif - -#if defined(CONFIG_CPU_FEROCEON) -# define MULTI_CACHE 1 -#endif - -#if defined(CONFIG_CPU_CACHE_V6) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v6 -# endif -#endif - -#if defined(CONFIG_CPU_CACHE_V7) -# ifdef _CACHE -# define MULTI_CACHE 1 -# else -# define _CACHE v7 -# endif -#endif - -#if !defined(_CACHE) && !defined(MULTI_CACHE) -#error Unknown cache maintainence model -#endif - -/* * This flag is used to indicate that the page pointed to by a pte is clean * and does not require cleaning before returning it to the user. */ @@ -249,19 +132,11 @@ extern struct cpu_cache_fns cpu_cache; * visible to the CPU. */ #define dmac_map_area cpu_cache.dma_map_area -#define dmac_unmap_area cpu_cache.dma_unmap_area +#define dmac_unmap_area cpu_cache.dma_unmap_area #define dmac_flush_range cpu_cache.dma_flush_range #else -#define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) -#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) -#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) -#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) -#define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) -#define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range) -#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area) - extern void __cpuc_flush_icache_all(void); extern void __cpuc_flush_kern_all(void); extern void __cpuc_flush_user_all(void); @@ -276,10 +151,6 @@ extern void __cpuc_flush_dcache_area(void *, size_t); * is visible to DMA, or data written by DMA to system memory is * visible to the CPU. */ -#define dmac_map_area __glue(_CACHE,_dma_map_area) -#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) -#define dmac_flush_range __glue(_CACHE,_dma_flush_range) - extern void dmac_map_area(const void *, size_t, int); extern void dmac_unmap_area(const void *, size_t, int); extern void dmac_flush_range(const void *, const void *); diff --git a/arch/arm/include/asm/cpu-multi32.h b/arch/arm/include/asm/cpu-multi32.h deleted file mode 100644 index e2b5b0b2116a..000000000000 --- a/arch/arm/include/asm/cpu-multi32.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * arch/arm/include/asm/cpu-multi32.h - * - * Copyright (C) 2000 Russell King - * - * 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 <asm/page.h> - -struct mm_struct; - -/* - * Don't change this structure - ASM code - * relies on it. - */ -extern struct processor { - /* MISC - * get data abort address/flags - */ - void (*_data_abort)(unsigned long pc); - /* - * Retrieve prefetch fault address - */ - unsigned long (*_prefetch_abort)(unsigned long lr); - /* - * Set up any processor specifics - */ - void (*_proc_init)(void); - /* - * Disable any processor specifics - */ - void (*_proc_fin)(void); - /* - * Special stuff for a reset - */ - void (*reset)(unsigned long addr) __attribute__((noreturn)); - /* - * Idle the processor - */ - int (*_do_idle)(void); - /* - * Processor architecture specific - */ - /* - * clean a virtual address range from the - * D-cache without flushing the cache. - */ - void (*dcache_clean_area)(void *addr, int size); - - /* - * Set the page table - */ - void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm); - /* - * Set a possibly extended PTE. Non-extended PTEs should - * ignore 'ext'. - */ - void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext); -} processor; - -#define cpu_proc_init() processor._proc_init() -#define cpu_proc_fin() processor._proc_fin() -#define cpu_reset(addr) processor.reset(addr) -#define cpu_do_idle() processor._do_idle() -#define cpu_dcache_clean_area(addr,sz) processor.dcache_clean_area(addr,sz) -#define cpu_set_pte_ext(ptep,pte,ext) processor.set_pte_ext(ptep,pte,ext) -#define cpu_do_switch_mm(pgd,mm) processor.switch_mm(pgd,mm) diff --git a/arch/arm/include/asm/cpu-single.h b/arch/arm/include/asm/cpu-single.h deleted file mode 100644 index f073a6d2a406..000000000000 --- a/arch/arm/include/asm/cpu-single.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * arch/arm/include/asm/cpu-single.h - * - * Copyright (C) 2000 Russell King - * - * 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. - */ -/* - * Single CPU - */ -#ifdef __STDC__ -#define __catify_fn(name,x) name##x -#else -#define __catify_fn(name,x) name/**/x -#endif -#define __cpu_fn(name,x) __catify_fn(name,x) - -/* - * If we are supporting multiple CPUs, then we must use a table of - * function pointers for this lot. Otherwise, we can optimise the - * table away. - */ -#define cpu_proc_init __cpu_fn(CPU_NAME,_proc_init) -#define cpu_proc_fin __cpu_fn(CPU_NAME,_proc_fin) -#define cpu_reset __cpu_fn(CPU_NAME,_reset) -#define cpu_do_idle __cpu_fn(CPU_NAME,_do_idle) -#define cpu_dcache_clean_area __cpu_fn(CPU_NAME,_dcache_clean_area) -#define cpu_do_switch_mm __cpu_fn(CPU_NAME,_switch_mm) -#define cpu_set_pte_ext __cpu_fn(CPU_NAME,_set_pte_ext) - -#include <asm/page.h> - -struct mm_struct; - -/* declare all the functions as extern */ -extern void cpu_proc_init(void); -extern void cpu_proc_fin(void); -extern int cpu_do_idle(void); -extern void cpu_dcache_clean_area(void *, int); -extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); -extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); -extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index 20ae96cc0020..ed5bc9e05a4e 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -23,6 +23,8 @@ #define CPUID_EXT_ISAR4 "c2, 4" #define CPUID_EXT_ISAR5 "c2, 5" +extern unsigned int processor_id; + #ifdef CONFIG_CPU_CP15 #define read_cpuid(reg) \ ({ \ @@ -43,7 +45,6 @@ __val; \ }) #else -extern unsigned int processor_id; #define read_cpuid(reg) (processor_id) #define read_cpuid_ext(reg) 0 #endif diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h new file mode 100644 index 000000000000..de5354746924 --- /dev/null +++ b/arch/arm/include/asm/fncpy.h @@ -0,0 +1,94 @@ +/* + * arch/arm/include/asm/fncpy.h - helper macros for function body copying + * + * Copyright (C) 2011 Linaro 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 + */ + +/* + * These macros are intended for use when there is a need to copy a low-level + * function body into special memory. + * + * For example, when reconfiguring the SDRAM controller, the code doing the + * reconfiguration may need to run from SRAM. + * + * NOTE: that the copied function body must be entirely self-contained and + * position-independent in order for this to work properly. + * + * NOTE: in order for embedded literals and data to get referenced correctly, + * the alignment of functions must be preserved when copying. To ensure this, + * the source and destination addresses for fncpy() must be aligned to a + * multiple of 8 bytes: you will be get a BUG() if this condition is not met. + * You will typically need a ".align 3" directive in the assembler where the + * function to be copied is defined, and ensure that your allocator for the + * destination buffer returns 8-byte-aligned pointers. + * + * Typical usage example: + * + * extern int f(args); + * extern uint32_t size_of_f; + * int (*copied_f)(args); + * void *sram_buffer; + * + * copied_f = fncpy(sram_buffer, &f, size_of_f); + * + * ... later, call the function: ... + * + * copied_f(args); + * + * The size of the function to be copied can't be determined from C: + * this must be determined by other means, such as adding assmbler directives + * in the file where f is defined. + */ + +#ifndef __ASM_FNCPY_H +#define __ASM_FNCPY_H + +#include <linux/types.h> +#include <linux/string.h> + +#include <asm/bug.h> +#include <asm/cacheflush.h> + +/* + * Minimum alignment requirement for the source and destination addresses + * for function copying. + */ +#define FNCPY_ALIGN 8 + +#define fncpy(dest_buf, funcp, size) ({ \ + uintptr_t __funcp_address; \ + typeof(funcp) __result; \ + \ + asm("" : "=r" (__funcp_address) : "0" (funcp)); \ + \ + /* \ + * Ensure alignment of source and destination addresses, \ + * disregarding the function's Thumb bit: \ + */ \ + BUG_ON((uintptr_t)(dest_buf) & (FNCPY_ALIGN - 1) || \ + (__funcp_address & ~(uintptr_t)1 & (FNCPY_ALIGN - 1))); \ + \ + memcpy(dest_buf, (void const *)(__funcp_address & ~1), size); \ + flush_icache_range((unsigned long)(dest_buf), \ + (unsigned long)(dest_buf) + (size)); \ + \ + asm("" : "=r" (__result) \ + : "0" ((uintptr_t)(dest_buf) | (__funcp_address & 1))); \ + \ + __result; \ +}) + +#endif /* !__ASM_FNCPY_H */ diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h new file mode 100644 index 000000000000..c7afbc552c7f --- /dev/null +++ b/arch/arm/include/asm/glue-cache.h @@ -0,0 +1,146 @@ +/* + * arch/arm/include/asm/glue-cache.h + * + * Copyright (C) 1999-2002 Russell King + * + * 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_GLUE_CACHE_H +#define ASM_GLUE_CACHE_H + +#include <asm/glue.h> + +/* + * Cache Model + * =========== + */ +#undef _CACHE +#undef MULTI_CACHE + +#if defined(CONFIG_CPU_CACHE_V3) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE v3 +# endif +#endif + +#if defined(CONFIG_CPU_CACHE_V4) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE v4 +# endif +#endif + +#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ + defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \ + defined(CONFIG_CPU_ARM1026) +# define MULTI_CACHE 1 +#endif + +#if defined(CONFIG_CPU_FA526) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE fa +# endif +#endif + +#if defined(CONFIG_CPU_ARM926T) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE arm926 +# endif +#endif + +#if defined(CONFIG_CPU_ARM940T) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE arm940 +# endif +#endif + +#if defined(CONFIG_CPU_ARM946E) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE arm946 +# endif +#endif + +#if defined(CONFIG_CPU_CACHE_V4WB) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE v4wb +# endif +#endif + +#if defined(CONFIG_CPU_XSCALE) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE xscale +# endif +#endif + +#if defined(CONFIG_CPU_XSC3) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE xsc3 +# endif +#endif + +#if defined(CONFIG_CPU_MOHAWK) +# ifdef _CACHE +# define MULTI_CACHE 1 +# else +# define _CACHE mohawk +# endif +#endif + +#if defined(CONFIG_CPU_FEROCEON) +# define MULTI_CACHE 1 +#endif + +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) +//# ifdef _CACHE +# define MULTI_CACHE 1 +//# else +//# define _CACHE v6 +//# endif +#endif + +#if defined(CONFIG_CPU_V7) +//# ifdef _CACHE +# define MULTI_CACHE 1 +//# else +//# define _CACHE v7 +//# endif +#endif + +#if !defined(_CACHE) && !defined(MULTI_CACHE) +#error Unknown cache maintainence model +#endif + +#ifndef MULTI_CACHE +#define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) +#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) +#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) +#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) +#define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) +#define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range) +#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area) + +#define dmac_map_area __glue(_CACHE,_dma_map_area) +#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) +#define dmac_flush_range __glue(_CACHE,_dma_flush_range) +#endif + +#endif diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h new file mode 100644 index 000000000000..354d571e8bcc --- /dev/null +++ b/arch/arm/include/asm/glue-df.h @@ -0,0 +1,110 @@ +/* + * arch/arm/include/asm/glue-df.h + * + * Copyright (C) 1997-1999 Russell King + * Copyright (C) 2000-2002 Deep Blue Solutions Ltd. + * + * 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_GLUE_DF_H +#define ASM_GLUE_DF_H + +#include <asm/glue.h> + +/* + * Data Abort Model + * ================ + * + * We have the following to choose from: + * arm6 - ARM6 style + * arm7 - ARM7 style + * v4_early - ARMv4 without Thumb early abort handler + * v4t_late - ARMv4 with Thumb late abort handler + * v4t_early - ARMv4 with Thumb early abort handler + * v5tej_early - ARMv5 with Thumb and Java early abort handler + * xscale - ARMv5 with Thumb with Xscale extensions + * v6_early - ARMv6 generic early abort handler + * v7_early - ARMv7 generic early abort handler + */ +#undef CPU_DABORT_HANDLER +#undef MULTI_DABORT + +#if defined(CONFIG_CPU_ARM610) +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER cpu_arm6_data_abort +# endif +#endif + +#if defined(CONFIG_CPU_ARM710) +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER cpu_arm7_data_abort +# endif +#endif + +#ifdef CONFIG_CPU_ABRT_LV4T +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v4t_late_abort +# endif +#endif + +#ifdef CONFIG_CPU_ABRT_EV4 +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v4_early_abort +# endif +#endif + +#ifdef CONFIG_CPU_ABRT_EV4T +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v4t_early_abort +# endif +#endif + +#ifdef CONFIG_CPU_ABRT_EV5TJ +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v5tj_early_abort +# endif +#endif + +#ifdef CONFIG_CPU_ABRT_EV5T +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v5t_early_abort +# endif +#endif + +#ifdef CONFIG_CPU_ABRT_EV6 +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v6_early_abort +# endif +#endif + +#ifdef CONFIG_CPU_ABRT_EV7 +# ifdef CPU_DABORT_HANDLER +# define MULTI_DABORT 1 +# else +# define CPU_DABORT_HANDLER v7_early_abort +# endif +#endif + +#ifndef CPU_DABORT_HANDLER +#error Unknown data abort handler type +#endif + +#endif diff --git a/arch/arm/include/asm/glue-pf.h b/arch/arm/include/asm/glue-pf.h new file mode 100644 index 000000000000..d385f37c13f0 --- /dev/null +++ b/arch/arm/include/asm/glue-pf.h @@ -0,0 +1,57 @@ +/* + * arch/arm/include/asm/glue-pf.h + * + * Copyright (C) 1997-1999 Russell King + * Copyright (C) 2000-2002 Deep Blue Solutions Ltd. + * + * 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_GLUE_PF_H +#define ASM_GLUE_PF_H + +#include <asm/glue.h> + +/* + * Prefetch Abort Model + * ================ + * + * We have the following to choose from: + * legacy - no IFSR, no IFAR + * v6 - ARMv6: IFSR, no IFAR + * v7 - ARMv7: IFSR and IFAR + */ + +#undef CPU_PABORT_HANDLER +#undef MULTI_PABORT + +#ifdef CONFIG_CPU_PABRT_LEGACY +# ifdef CPU_PABORT_HANDLER +# define MULTI_PABORT 1 +# else +# define CPU_PABORT_HANDLER legacy_pabort +# endif +#endif + +#ifdef CONFIG_CPU_PABRT_V6 +# ifdef CPU_PABORT_HANDLER +# define MULTI_PABORT 1 +# else +# define CPU_PABORT_HANDLER v6_pabort +# endif +#endif + +#ifdef CONFIG_CPU_PABRT_V7 +# ifdef CPU_PABORT_HANDLER +# define MULTI_PABORT 1 +# else +# define CPU_PABORT_HANDLER v7_pabort +# endif +#endif + +#ifndef CPU_PABORT_HANDLER +#error Unknown prefetch abort handler type +#endif + +#endif diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h new file mode 100644 index 000000000000..e2be7f142668 --- /dev/null +++ b/arch/arm/include/asm/glue-proc.h @@ -0,0 +1,264 @@ +/* + * arch/arm/include/asm/glue-proc.h + * + * Copyright (C) 1997-1999 Russell King + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * 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_GLUE_PROC_H +#define ASM_GLUE_PROC_H + +#include <asm/glue.h> + +/* + * Work out if we need multiple CPU support + */ +#undef MULTI_CPU +#undef CPU_NAME + +/* + * CPU_NAME - the prefix for CPU related functions + */ + +#ifdef CONFIG_CPU_ARM610 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm6 +# endif +#endif + +#ifdef CONFIG_CPU_ARM7TDMI +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm7tdmi +# endif +#endif + +#ifdef CONFIG_CPU_ARM710 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm7 +# endif +#endif + +#ifdef CONFIG_CPU_ARM720T +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm720 +# endif +#endif + +#ifdef CONFIG_CPU_ARM740T +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm740 +# endif +#endif + +#ifdef CONFIG_CPU_ARM9TDMI +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm9tdmi +# endif +#endif + +#ifdef CONFIG_CPU_ARM920T +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm920 +# endif +#endif + +#ifdef CONFIG_CPU_ARM922T +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm922 +# endif +#endif + +#ifdef CONFIG_CPU_FA526 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_fa526 +# endif +#endif + +#ifdef CONFIG_CPU_ARM925T +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm925 +# endif +#endif + +#ifdef CONFIG_CPU_ARM926T +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm926 +# endif +#endif + +#ifdef CONFIG_CPU_ARM940T +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm940 +# endif +#endif + +#ifdef CONFIG_CPU_ARM946E +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm946 +# endif +#endif + +#ifdef CONFIG_CPU_SA110 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_sa110 +# endif +#endif + +#ifdef CONFIG_CPU_SA1100 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_sa1100 +# endif +#endif + +#ifdef CONFIG_CPU_ARM1020 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm1020 +# endif +#endif + +#ifdef CONFIG_CPU_ARM1020E +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm1020e +# endif +#endif + +#ifdef CONFIG_CPU_ARM1022 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm1022 +# endif +#endif + +#ifdef CONFIG_CPU_ARM1026 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_arm1026 +# endif +#endif + +#ifdef CONFIG_CPU_XSCALE +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_xscale +# endif +#endif + +#ifdef CONFIG_CPU_XSC3 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_xsc3 +# endif +#endif + +#ifdef CONFIG_CPU_MOHAWK +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_mohawk +# endif +#endif + +#ifdef CONFIG_CPU_FEROCEON +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_feroceon +# endif +#endif + +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_v6 +# endif +#endif + +#ifdef CONFIG_CPU_V7 +# ifdef CPU_NAME +# undef MULTI_CPU +# define MULTI_CPU +# else +# define CPU_NAME cpu_v7 +# endif +#endif + +#ifndef MULTI_CPU +#define cpu_proc_init __glue(CPU_NAME,_proc_init) +#define cpu_proc_fin __glue(CPU_NAME,_proc_fin) +#define cpu_reset __glue(CPU_NAME,_reset) +#define cpu_do_idle __glue(CPU_NAME,_do_idle) +#define cpu_dcache_clean_area __glue(CPU_NAME,_dcache_clean_area) +#define cpu_do_switch_mm __glue(CPU_NAME,_switch_mm) +#define cpu_set_pte_ext __glue(CPU_NAME,_set_pte_ext) +#define cpu_suspend_size __glue(CPU_NAME,_suspend_size) +#define cpu_do_suspend __glue(CPU_NAME,_do_suspend) +#define cpu_do_resume __glue(CPU_NAME,_do_resume) +#endif + +#endif diff --git a/arch/arm/include/asm/glue.h b/arch/arm/include/asm/glue.h index 234a3fc1c78e..0ec35d1698aa 100644 --- a/arch/arm/include/asm/glue.h +++ b/arch/arm/include/asm/glue.h @@ -15,7 +15,6 @@ */ #ifdef __KERNEL__ - #ifdef __STDC__ #define ____glue(name,fn) name##fn #else @@ -23,141 +22,4 @@ #endif #define __glue(name,fn) ____glue(name,fn) - - -/* - * Data Abort Model - * ================ - * - * We have the following to choose from: - * arm6 - ARM6 style - * arm7 - ARM7 style - * v4_early - ARMv4 without Thumb early abort handler - * v4t_late - ARMv4 with Thumb late abort handler - * v4t_early - ARMv4 with Thumb early abort handler - * v5tej_early - ARMv5 with Thumb and Java early abort handler - * xscale - ARMv5 with Thumb with Xscale extensions - * v6_early - ARMv6 generic early abort handler - * v7_early - ARMv7 generic early abort handler - */ -#undef CPU_DABORT_HANDLER -#undef MULTI_DABORT - -#if defined(CONFIG_CPU_ARM610) -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER cpu_arm6_data_abort -# endif -#endif - -#if defined(CONFIG_CPU_ARM710) -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER cpu_arm7_data_abort -# endif -#endif - -#ifdef CONFIG_CPU_ABRT_LV4T -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER v4t_late_abort -# endif -#endif - -#ifdef CONFIG_CPU_ABRT_EV4 -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER v4_early_abort -# endif -#endif - -#ifdef CONFIG_CPU_ABRT_EV4T -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER v4t_early_abort -# endif -#endif - -#ifdef CONFIG_CPU_ABRT_EV5TJ -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER v5tj_early_abort -# endif -#endif - -#ifdef CONFIG_CPU_ABRT_EV5T -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER v5t_early_abort -# endif -#endif - -#ifdef CONFIG_CPU_ABRT_EV6 -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER v6_early_abort -# endif -#endif - -#ifdef CONFIG_CPU_ABRT_EV7 -# ifdef CPU_DABORT_HANDLER -# define MULTI_DABORT 1 -# else -# define CPU_DABORT_HANDLER v7_early_abort -# endif -#endif - -#ifndef CPU_DABORT_HANDLER -#error Unknown data abort handler type -#endif - -/* - * Prefetch Abort Model - * ================ - * - * We have the following to choose from: - * legacy - no IFSR, no IFAR - * v6 - ARMv6: IFSR, no IFAR - * v7 - ARMv7: IFSR and IFAR - */ - -#undef CPU_PABORT_HANDLER -#undef MULTI_PABORT - -#ifdef CONFIG_CPU_PABRT_LEGACY -# ifdef CPU_PABORT_HANDLER -# define MULTI_PABORT 1 -# else -# define CPU_PABORT_HANDLER legacy_pabort -# endif -#endif - -#ifdef CONFIG_CPU_PABRT_V6 -# ifdef CPU_PABORT_HANDLER -# define MULTI_PABORT 1 -# else -# define CPU_PABORT_HANDLER v6_pabort -# endif -#endif - -#ifdef CONFIG_CPU_PABRT_V7 -# ifdef CPU_PABORT_HANDLER -# define MULTI_PABORT 1 -# else -# define CPU_PABORT_HANDLER v7_pabort -# endif -#endif - -#ifndef CPU_PABORT_HANDLER -#error Unknown prefetch abort handler type -#endif - #endif diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 5aeec1e1735c..16bd48031583 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -36,6 +36,7 @@ #define L2X0_RAW_INTR_STAT 0x21C #define L2X0_INTR_CLEAR 0x220 #define L2X0_CACHE_SYNC 0x730 +#define L2X0_DUMMY_REG 0x740 #define L2X0_INV_LINE_PA 0x770 #define L2X0_INV_WAY 0x77C #define L2X0_CLEAN_LINE_PA 0x7B0 diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h index 84557d321001..0691f9dcc500 100644 --- a/arch/arm/include/asm/hardware/gic.h +++ b/arch/arm/include/asm/hardware/gic.h @@ -34,6 +34,7 @@ #ifndef __ASSEMBLY__ extern void __iomem *gic_cpu_base_addr; +extern struct irq_chip gic_arch_extn; void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); void gic_secondary_init(unsigned int); diff --git a/arch/arm/include/asm/hardware/sp810.h b/arch/arm/include/asm/hardware/sp810.h index a101f10bb5b1..e0d1c0cfa548 100644 --- a/arch/arm/include/asm/hardware/sp810.h +++ b/arch/arm/include/asm/hardware/sp810.h @@ -50,8 +50,17 @@ #define SCPCELLID2 0xFF8 #define SCPCELLID3 0xFFC +#define SCCTRL_TIMEREN0SEL_REFCLK (0 << 15) +#define SCCTRL_TIMEREN0SEL_TIMCLK (1 << 15) + +#define SCCTRL_TIMEREN1SEL_REFCLK (0 << 17) +#define SCCTRL_TIMEREN1SEL_TIMCLK (1 << 17) + static inline void sysctl_soft_reset(void __iomem *base) { + /* switch to slow mode */ + writel(0x2, base + SCCTRL); + /* writing any value to SCSYSSTAT reg will reset system */ writel(0, base + SCSYSSTAT); } diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h index 7080e2c8fa62..a4edd19dd3d6 100644 --- a/arch/arm/include/asm/highmem.h +++ b/arch/arm/include/asm/highmem.h @@ -19,11 +19,36 @@ extern pte_t *pkmap_page_table; +extern void *kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +/* + * The reason for kmap_high_get() is to ensure that the currently kmap'd + * page usage count does not decrease to zero while we're using its + * existing virtual mapping in an atomic context. With a VIVT cache this + * is essential to do, but with a VIPT cache this is only an optimization + * so not to pay the price of establishing a second mapping if an existing + * one can be used. However, on platforms without hardware TLB maintenance + * broadcast, we simply cannot use ARCH_NEEDS_KMAP_HIGH_GET at all since + * the locking involved must also disable IRQs which is incompatible with + * the IPI mechanism used by global TLB operations. + */ #define ARCH_NEEDS_KMAP_HIGH_GET +#if defined(CONFIG_SMP) && defined(CONFIG_CPU_TLB_V6) +#undef ARCH_NEEDS_KMAP_HIGH_GET +#if defined(CONFIG_HIGHMEM) && defined(CONFIG_CPU_CACHE_VIVT) +#error "The sum of features in your kernel config cannot be supported together" +#endif +#endif -extern void *kmap_high(struct page *page); +#ifdef ARCH_NEEDS_KMAP_HIGH_GET extern void *kmap_high_get(struct page *page); -extern void kunmap_high(struct page *page); +#else +static inline void *kmap_high_get(struct page *page) +{ + return NULL; +} +#endif /* * The following functions are already defined by <linux/highmem.h> diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 20e0f7c9e03e..d66605dea55a 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -95,6 +95,15 @@ static inline void __iomem *__typesafe_io(unsigned long addr) return (void __iomem *)addr; } +/* IO barriers */ +#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE +#define __iormb() rmb() +#define __iowmb() wmb() +#else +#define __iormb() do { } while (0) +#define __iowmb() do { } while (0) +#endif + /* * Now, pick up the machine-defined IO definitions */ @@ -125,17 +134,17 @@ static inline void __iomem *__typesafe_io(unsigned long addr) * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space. */ #ifdef __io -#define outb(v,p) __raw_writeb(v,__io(p)) -#define outw(v,p) __raw_writew((__force __u16) \ - cpu_to_le16(v),__io(p)) -#define outl(v,p) __raw_writel((__force __u32) \ - cpu_to_le32(v),__io(p)) +#define outb(v,p) ({ __iowmb(); __raw_writeb(v,__io(p)); }) +#define outw(v,p) ({ __iowmb(); __raw_writew((__force __u16) \ + cpu_to_le16(v),__io(p)); }) +#define outl(v,p) ({ __iowmb(); __raw_writel((__force __u32) \ + cpu_to_le32(v),__io(p)); }) -#define inb(p) ({ __u8 __v = __raw_readb(__io(p)); __v; }) +#define inb(p) ({ __u8 __v = __raw_readb(__io(p)); __iormb(); __v; }) #define inw(p) ({ __u16 __v = le16_to_cpu((__force __le16) \ - __raw_readw(__io(p))); __v; }) + __raw_readw(__io(p))); __iormb(); __v; }) #define inl(p) ({ __u32 __v = le32_to_cpu((__force __le32) \ - __raw_readl(__io(p))); __v; }) + __raw_readl(__io(p))); __iormb(); __v; }) #define outsb(p,d,l) __raw_writesb(__io(p),d,l) #define outsw(p,d,l) __raw_writesw(__io(p),d,l) @@ -192,14 +201,6 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define writel_relaxed(v,c) ((void)__raw_writel((__force u32) \ cpu_to_le32(v),__mem_pci(c))) -#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE -#define __iormb() rmb() -#define __iowmb() wmb() -#else -#define __iormb() do { } while (0) -#define __iowmb() do { } while (0) -#endif - #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 3a0893a76a3b..bf13b814c1b8 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -15,10 +15,6 @@ struct meminfo; struct sys_timer; struct machine_desc { - /* - * Note! The first two elements are used - * by assembler code in head.S, head-common.S - */ unsigned int nr; /* architecture number */ const char *name; /* architecture name */ unsigned long boot_params; /* tagged list */ diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h index 22ac140edd9e..febe495d0c6e 100644 --- a/arch/arm/include/asm/mach/irq.h +++ b/arch/arm/include/asm/mach/irq.h @@ -34,4 +34,35 @@ do { \ raw_spin_unlock(&desc->lock); \ } while(0) +#ifndef __ASSEMBLY__ +/* + * Entry/exit functions for chained handlers where the primary IRQ chip + * may implement either fasteoi or level-trigger flow control. + */ +static inline void chained_irq_enter(struct irq_chip *chip, + struct irq_desc *desc) +{ + /* FastEOI controllers require no action on entry. */ + if (chip->irq_eoi) + return; + + if (chip->irq_mask_ack) { + chip->irq_mask_ack(&desc->irq_data); + } else { + chip->irq_mask(&desc->irq_data); + if (chip->irq_ack) + chip->irq_ack(&desc->irq_data); + } +} + +static inline void chained_irq_exit(struct irq_chip *chip, + struct irq_desc *desc) +{ + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); + else + chip->irq_unmask(&desc->irq_data); +} +#endif + #endif diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 23c2e8e5c0fa..d0ee74b7cf86 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -188,7 +188,7 @@ * translation for translating DMA addresses. Use the driver * DMA support - see dma-mapping.h. */ -static inline unsigned long virt_to_phys(void *x) +static inline unsigned long virt_to_phys(const volatile void *x) { return __virt_to_phys((unsigned long)(x)); } diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index fc1900925275..348d513afa92 100644 --- a/arch/arm/include/asm/outercache.h +++ b/arch/arm/include/asm/outercache.h @@ -31,6 +31,7 @@ struct outer_cache_fns { #ifdef CONFIG_OUTER_CACHE_SYNC void (*sync)(void); #endif + void (*set_debug)(unsigned long); }; #ifdef CONFIG_OUTER_CACHE diff --git a/arch/arm/include/asm/pgalloc.h b/arch/arm/include/asm/pgalloc.h index 9763be04f77e..22de005f159c 100644 --- a/arch/arm/include/asm/pgalloc.h +++ b/arch/arm/include/asm/pgalloc.h @@ -10,6 +10,8 @@ #ifndef _ASMARM_PGALLOC_H #define _ASMARM_PGALLOC_H +#include <linux/pagemap.h> + #include <asm/domain.h> #include <asm/pgtable-hwdef.h> #include <asm/processor.h> diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 296ca47489f9..8ec535e11fd7 100644 --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -13,250 +13,86 @@ #ifdef __KERNEL__ +#include <asm/glue-proc.h> +#include <asm/page.h> -/* - * Work out if we need multiple CPU support - */ -#undef MULTI_CPU -#undef CPU_NAME +#ifndef __ASSEMBLY__ + +struct mm_struct; /* - * CPU_NAME - the prefix for CPU related functions + * Don't change this structure - ASM code relies on it. */ - -#ifdef CONFIG_CPU_ARM610 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm6 -# endif -#endif - -#ifdef CONFIG_CPU_ARM7TDMI -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm7tdmi -# endif -#endif - -#ifdef CONFIG_CPU_ARM710 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm7 -# endif -#endif - -#ifdef CONFIG_CPU_ARM720T -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm720 -# endif -#endif - -#ifdef CONFIG_CPU_ARM740T -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm740 -# endif -#endif - -#ifdef CONFIG_CPU_ARM9TDMI -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm9tdmi -# endif -#endif - -#ifdef CONFIG_CPU_ARM920T -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm920 -# endif -#endif - -#ifdef CONFIG_CPU_ARM922T -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm922 -# endif -#endif - -#ifdef CONFIG_CPU_FA526 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_fa526 -# endif -#endif - -#ifdef CONFIG_CPU_ARM925T -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm925 -# endif -#endif - -#ifdef CONFIG_CPU_ARM926T -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm926 -# endif -#endif - -#ifdef CONFIG_CPU_ARM940T -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm940 -# endif -#endif - -#ifdef CONFIG_CPU_ARM946E -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm946 -# endif -#endif - -#ifdef CONFIG_CPU_SA110 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_sa110 -# endif -#endif - -#ifdef CONFIG_CPU_SA1100 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_sa1100 -# endif -#endif - -#ifdef CONFIG_CPU_ARM1020 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm1020 -# endif -#endif - -#ifdef CONFIG_CPU_ARM1020E -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm1020e -# endif -#endif - -#ifdef CONFIG_CPU_ARM1022 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm1022 -# endif -#endif - -#ifdef CONFIG_CPU_ARM1026 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_arm1026 -# endif -#endif - -#ifdef CONFIG_CPU_XSCALE -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_xscale -# endif -#endif - -#ifdef CONFIG_CPU_XSC3 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_xsc3 -# endif -#endif - -#ifdef CONFIG_CPU_MOHAWK -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_mohawk -# endif -#endif - -#ifdef CONFIG_CPU_FEROCEON -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_feroceon -# endif -#endif - -#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_v6 -# endif -#endif - -#ifdef CONFIG_CPU_V7 -# ifdef CPU_NAME -# undef MULTI_CPU -# define MULTI_CPU -# else -# define CPU_NAME cpu_v7 -# endif -#endif - -#ifndef __ASSEMBLY__ +extern struct processor { + /* MISC + * get data abort address/flags + */ + void (*_data_abort)(unsigned long pc); + /* + * Retrieve prefetch fault address + */ + unsigned long (*_prefetch_abort)(unsigned long lr); + /* + * Set up any processor specifics + */ + void (*_proc_init)(void); + /* + * Disable any processor specifics + */ + void (*_proc_fin)(void); + /* + * Special stuff for a reset + */ + void (*reset)(unsigned long addr) __attribute__((noreturn)); + /* + * Idle the processor + */ + int (*_do_idle)(void); + /* + * Processor architecture specific + */ + /* + * clean a virtual address range from the + * D-cache without flushing the cache. + */ + void (*dcache_clean_area)(void *addr, int size); + + /* + * Set the page table + */ + void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm); + /* + * Set a possibly extended PTE. Non-extended PTEs should + * ignore 'ext'. + */ + void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext); + + /* Suspend/resume */ + unsigned int suspend_size; + void (*do_suspend)(void *); + void (*do_resume)(void *); +} processor; #ifndef MULTI_CPU -#include <asm/cpu-single.h> +extern void cpu_proc_init(void); +extern void cpu_proc_fin(void); +extern int cpu_do_idle(void); +extern void cpu_dcache_clean_area(void *, int); +extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm); +extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext); +extern void cpu_reset(unsigned long addr) __attribute__((noreturn)); #else -#include <asm/cpu-multi32.h> +#define cpu_proc_init() processor._proc_init() +#define cpu_proc_fin() processor._proc_fin() +#define cpu_reset(addr) processor.reset(addr) +#define cpu_do_idle() processor._do_idle() +#define cpu_dcache_clean_area(addr,sz) processor.dcache_clean_area(addr,sz) +#define cpu_set_pte_ext(ptep,pte,ext) processor.set_pte_ext(ptep,pte,ext) +#define cpu_do_switch_mm(pgd,mm) processor.switch_mm(pgd,mm) #endif +extern void cpu_resume(void); + #include <asm/memory.h> #ifdef CONFIG_MMU diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 67357baaeeeb..b2d9df5667af 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h @@ -29,19 +29,7 @@ #define STACK_TOP_MAX TASK_SIZE #endif -union debug_insn { - u32 arm; - u16 thumb; -}; - -struct debug_entry { - u32 address; - union debug_insn insn; -}; - struct debug_info { - int nsaved; - struct debug_entry bp[2]; #ifdef CONFIG_HAVE_HW_BREAKPOINT struct perf_event *hbp[ARM_MAX_HBP_SLOTS]; #endif @@ -95,7 +83,7 @@ extern void release_thread(struct task_struct *); unsigned long get_wchan(struct task_struct *p); -#if __LINUX_ARM_ARCH__ == 6 +#if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327) #define cpu_relax() smp_mb() #else #define cpu_relax() barrier() diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 783d50f32618..a8ff22b2a391 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -130,8 +130,6 @@ struct pt_regs { #ifdef __KERNEL__ -#define arch_has_single_step() (1) - #define user_mode(regs) \ (((regs)->ARM_cpsr & 0xf) == 0) diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h index 2376835015d6..4eb6d005ffaa 100644 --- a/arch/arm/include/asm/smp_scu.h +++ b/arch/arm/include/asm/smp_scu.h @@ -1,7 +1,14 @@ #ifndef __ASMARM_ARCH_SCU_H #define __ASMARM_ARCH_SCU_H +#define SCU_PM_NORMAL 0 +#define SCU_PM_DORMANT 2 +#define SCU_PM_POWEROFF 3 + +#ifndef __ASSEMBLER__ unsigned int scu_get_core_count(void __iomem *); void scu_enable(void __iomem *); +int scu_power_mode(void __iomem *, unsigned int); +#endif #endif diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index f41a6f57cd12..82dfe5d0c41e 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h @@ -18,16 +18,34 @@ #define __ASMARM_TLB_H #include <asm/cacheflush.h> -#include <asm/tlbflush.h> #ifndef CONFIG_MMU #include <linux/pagemap.h> + +#define tlb_flush(tlb) ((void) tlb) + #include <asm-generic/tlb.h> #else /* !CONFIG_MMU */ +#include <linux/swap.h> #include <asm/pgalloc.h> +#include <asm/tlbflush.h> + +/* + * We need to delay page freeing for SMP as other CPUs can access pages + * which have been removed but not yet had their TLB entries invalidated. + * Also, as ARMv7 speculative prefetch can drag new entries into the TLB, + * we need to apply this same delaying tactic to ensure correct operation. + */ +#if defined(CONFIG_SMP) || defined(CONFIG_CPU_32v7) +#define tlb_fast_mode(tlb) 0 +#define FREE_PTE_NR 500 +#else +#define tlb_fast_mode(tlb) 1 +#define FREE_PTE_NR 0 +#endif /* * TLB handling. This allows us to remove pages from the page @@ -36,12 +54,58 @@ struct mmu_gather { struct mm_struct *mm; unsigned int fullmm; + struct vm_area_struct *vma; unsigned long range_start; unsigned long range_end; + unsigned int nr; + struct page *pages[FREE_PTE_NR]; }; DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); +/* + * This is unnecessarily complex. There's three ways the TLB shootdown + * code is used: + * 1. Unmapping a range of vmas. See zap_page_range(), unmap_region(). + * tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called. + * tlb->vma will be non-NULL. + * 2. Unmapping all vmas. See exit_mmap(). + * tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called. + * tlb->vma will be non-NULL. Additionally, page tables will be freed. + * 3. Unmapping argument pages. See shift_arg_pages(). + * tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called. + * tlb->vma will be NULL. + */ +static inline void tlb_flush(struct mmu_gather *tlb) +{ + if (tlb->fullmm || !tlb->vma) + flush_tlb_mm(tlb->mm); + else if (tlb->range_end > 0) { + flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end); + tlb->range_start = TASK_SIZE; + tlb->range_end = 0; + } +} + +static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr) +{ + if (!tlb->fullmm) { + if (addr < tlb->range_start) + tlb->range_start = addr; + if (addr + PAGE_SIZE > tlb->range_end) + tlb->range_end = addr + PAGE_SIZE; + } +} + +static inline void tlb_flush_mmu(struct mmu_gather *tlb) +{ + tlb_flush(tlb); + if (!tlb_fast_mode(tlb)) { + free_pages_and_swap_cache(tlb->pages, tlb->nr); + tlb->nr = 0; + } +} + static inline struct mmu_gather * tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) { @@ -49,6 +113,8 @@ tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) tlb->mm = mm; tlb->fullmm = full_mm_flush; + tlb->vma = NULL; + tlb->nr = 0; return tlb; } @@ -56,8 +122,7 @@ tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) static inline void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { - if (tlb->fullmm) - flush_tlb_mm(tlb->mm); + tlb_flush_mmu(tlb); /* keep the page table cache within bounds */ check_pgt_cache(); @@ -71,12 +136,7 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) static inline void tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr) { - if (!tlb->fullmm) { - if (addr < tlb->range_start) - tlb->range_start = addr; - if (addr + PAGE_SIZE > tlb->range_end) - tlb->range_end = addr + PAGE_SIZE; - } + tlb_add_flush(tlb, addr); } /* @@ -89,6 +149,7 @@ tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) { if (!tlb->fullmm) { flush_cache_range(vma, vma->vm_start, vma->vm_end); + tlb->vma = vma; tlb->range_start = TASK_SIZE; tlb->range_end = 0; } @@ -97,12 +158,30 @@ tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) static inline void tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) { - if (!tlb->fullmm && tlb->range_end > 0) - flush_tlb_range(vma, tlb->range_start, tlb->range_end); + if (!tlb->fullmm) + tlb_flush(tlb); +} + +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + if (tlb_fast_mode(tlb)) { + free_page_and_swap_cache(page); + } else { + tlb->pages[tlb->nr++] = page; + if (tlb->nr >= FREE_PTE_NR) + tlb_flush_mmu(tlb); + } +} + +static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, + unsigned long addr) +{ + pgtable_page_dtor(pte); + tlb_add_flush(tlb, addr); + tlb_remove_page(tlb, pte); } -#define tlb_remove_page(tlb,page) free_page_and_swap_cache(page) -#define pte_free_tlb(tlb, ptep, addr) pte_free((tlb)->mm, ptep) +#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr) #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/tlbflush.h b/arch/arm/include/asm/tlbflush.h index ce7378ea15a2..d2005de383b8 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -10,12 +10,7 @@ #ifndef _ASMARM_TLBFLUSH_H #define _ASMARM_TLBFLUSH_H - -#ifndef CONFIG_MMU - -#define tlb_flush(tlb) ((void) tlb) - -#else /* CONFIG_MMU */ +#ifdef CONFIG_MMU #include <asm/glue.h> diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index 1b960d5ef6a5..f90756dc16dc 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h @@ -45,6 +45,7 @@ static inline int in_exception_text(unsigned long ptr) extern void __init early_trap_init(void); extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); +extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs); extern void *vectors_page; diff --git a/arch/arm/include/asm/user.h b/arch/arm/include/asm/user.h index 05ac4b06876a..35917b3a97f9 100644 --- a/arch/arm/include/asm/user.h +++ b/arch/arm/include/asm/user.h @@ -71,7 +71,7 @@ struct user{ /* the registers. */ unsigned long magic; /* To uniquely identify a core file */ char u_comm[32]; /* User command that was responsible */ - int u_debugreg[8]; + int u_debugreg[8]; /* No longer used */ struct user_fp u_fp; /* FP state */ struct user_fp_struct * u_fp0;/* Used by gdb to help find the values for */ /* the FP registers. */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 185ee822c935..74554f1742d7 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_MODULES) += armksyms.o module.o obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_PCI) += bios32.o isa.o +obj-$(CONFIG_PM) += sleep.o obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_SMP) += smp.o smp_tlb.o obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 82da66172132..927522cfc12e 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -13,6 +13,9 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/dma-mapping.h> +#include <asm/cacheflush.h> +#include <asm/glue-df.h> +#include <asm/glue-pf.h> #include <asm/mach/arch.h> #include <asm/thread_info.h> #include <asm/memory.h> @@ -114,6 +117,14 @@ int main(void) #ifdef MULTI_PABORT DEFINE(PROCESSOR_PABT_FUNC, offsetof(struct processor, _prefetch_abort)); #endif +#ifdef MULTI_CPU + DEFINE(CPU_SLEEP_SIZE, offsetof(struct processor, suspend_size)); + DEFINE(CPU_DO_SUSPEND, offsetof(struct processor, do_suspend)); + DEFINE(CPU_DO_RESUME, offsetof(struct processor, do_resume)); +#endif +#ifdef MULTI_CACHE + DEFINE(CACHE_FLUSH_KERN_ALL, offsetof(struct cpu_cache_fns, flush_kern_all)); +#endif BLANK(); DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index c6273a3bfc25..d86fcd44b220 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -583,6 +583,11 @@ void __init pci_common_init(struct hw_pci *hw) * Assign resources. */ pci_bus_assign_resources(bus); + + /* + * Enable bridges + */ + pci_enable_bridges(bus); } /* diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 2b46fea36c9f..e8d885676807 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -16,7 +16,8 @@ */ #include <asm/memory.h> -#include <asm/glue.h> +#include <asm/glue-df.h> +#include <asm/glue-pf.h> #include <asm/vfpmacros.h> #include <mach/entry-macro.S> #include <asm/thread_notify.h> diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 8f57515bbdb0..c84b57d27d07 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -25,83 +25,6 @@ * machine ID for example). */ __HEAD -__error_a: -#ifdef CONFIG_DEBUG_LL - mov r4, r1 @ preserve machine ID - adr r0, str_a1 - bl printascii - mov r0, r4 - bl printhex8 - adr r0, str_a2 - bl printascii - adr r3, __lookup_machine_type_data - ldmia r3, {r4, r5, r6} @ get machine desc list - sub r4, r3, r4 @ get offset between virt&phys - add r5, r5, r4 @ convert virt addresses to - add r6, r6, r4 @ physical address space -1: ldr r0, [r5, #MACHINFO_TYPE] @ get machine type - bl printhex8 - mov r0, #'\t' - bl printch - ldr r0, [r5, #MACHINFO_NAME] @ get machine name - add r0, r0, r4 - bl printascii - mov r0, #'\n' - bl printch - add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc - cmp r5, r6 - blo 1b - adr r0, str_a3 - bl printascii - b __error -ENDPROC(__error_a) - -str_a1: .asciz "\nError: unrecognized/unsupported machine ID (r1 = 0x" -str_a2: .asciz ").\n\nAvailable machine support:\n\nID (hex)\tNAME\n" -str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n" - .align -#else - b __error -#endif - -/* - * Lookup machine architecture in the linker-build list of architectures. - * Note that we can't use the absolute addresses for the __arch_info - * lists since we aren't running with the MMU on (and therefore, we are - * not in the correct address space). We have to calculate the offset. - * - * r1 = machine architecture number - * Returns: - * r3, r4, r6 corrupted - * r5 = mach_info pointer in physical address space - */ -__lookup_machine_type: - adr r3, __lookup_machine_type_data - ldmia r3, {r4, r5, r6} - sub r3, r3, r4 @ get offset between virt&phys - add r5, r5, r3 @ convert virt addresses to - add r6, r6, r3 @ physical address space -1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type - teq r3, r1 @ matches loader number? - beq 2f @ found - add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc - cmp r5, r6 - blo 1b - mov r5, #0 @ unknown machine -2: mov pc, lr -ENDPROC(__lookup_machine_type) - -/* - * Look in arch/arm/kernel/arch.[ch] for information about the - * __arch_info structures. - */ - .align 2 - .type __lookup_machine_type_data, %object -__lookup_machine_type_data: - .long . - .long __arch_info_begin - .long __arch_info_end - .size __lookup_machine_type_data, . - __lookup_machine_type_data /* Determine validity of the r2 atags pointer. The heuristic requires * that the pointer be aligned, in the first 16k of physical RAM and @@ -109,8 +32,6 @@ __lookup_machine_type_data: * of this function may be more lenient with the physical address and * may also be able to move the ATAGS block if necessary. * - * r8 = machinfo - * * Returns: * r2 either valid atags pointer, or zero * r5, r6 corrupted @@ -185,17 +106,6 @@ __mmap_switched_data: .size __mmap_switched_data, . - __mmap_switched_data /* - * This provides a C-API version of __lookup_machine_type - */ -ENTRY(lookup_machine_type) - stmfd sp!, {r4 - r6, lr} - mov r1, r0 - bl __lookup_machine_type - mov r0, r5 - ldmfd sp!, {r4 - r6, pc} -ENDPROC(lookup_machine_type) - -/* * This provides a C-API version of __lookup_processor_type */ ENTRY(lookup_processor_type) diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S index 814ce1a73270..6b1e0ad9ec3b 100644 --- a/arch/arm/kernel/head-nommu.S +++ b/arch/arm/kernel/head-nommu.S @@ -44,9 +44,6 @@ ENTRY(stext) bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)? beq __error_p @ yes, error 'p' - bl __lookup_machine_type @ r5=machinfo - movs r8, r5 @ invalid machine (r5=0)? - beq __error_a @ yes, error 'a' adr lr, BSYM(__after_proc_init) @ return (PIC) address ARM( add pc, r10, #PROCINFO_INITFUNC ) diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index f17d9a09e8fb..60fe2795f4a3 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -87,14 +87,10 @@ ENTRY(stext) movs r10, r5 @ invalid processor (r5=0)? THUMB( it eq ) @ force fixup-able long branch encoding beq __error_p @ yes, error 'p' - bl __lookup_machine_type @ r5=machinfo - movs r8, r5 @ invalid machine (r5=0)? - THUMB( it eq ) @ force fixup-able long branch encoding - beq __error_a @ yes, error 'a' /* * r1 = machine no, r2 = atags, - * r8 = machinfo, r9 = cpuid, r10 = procinfo + * r9 = cpuid, r10 = procinfo */ bl __vet_atags #ifdef CONFIG_SMP_ON_UP @@ -105,7 +101,7 @@ ENTRY(stext) /* * The following calls CPU specific code in a position independent * manner. See arch/arm/mm/proc-*.S for details. r10 = base of - * xxx_proc_info structure selected by __lookup_machine_type + * xxx_proc_info structure selected by __lookup_processor_type * above. On return, the CPU will be ready for the MMU to be * turned on, and r0 will hold the CPU control register value. */ @@ -124,7 +120,6 @@ ENDPROC(stext) * amount which are required to get the kernel running, which * generally means mapping in the kernel code. * - * r8 = machinfo * r9 = cpuid * r10 = procinfo * @@ -391,25 +386,24 @@ ENDPROC(__turn_mmu_on) #ifdef CONFIG_SMP_ON_UP + __INIT __fixup_smp: - mov r4, #0x00070000 - orr r3, r4, #0xff000000 @ mask 0xff070000 - orr r4, r4, #0x41000000 @ val 0x41070000 - and r0, r9, r3 - teq r0, r4 @ ARM CPU and ARMv6/v7? + and r3, r9, #0x000f0000 @ architecture version + teq r3, #0x000f0000 @ CPU ID supported? bne __fixup_smp_on_up @ no, assume UP - orr r3, r3, #0x0000ff00 - orr r3, r3, #0x000000f0 @ mask 0xff07fff0 + bic r3, r9, #0x00ff0000 + bic r3, r3, #0x0000000f @ mask 0xff00fff0 + mov r4, #0x41000000 orr r4, r4, #0x0000b000 - orr r4, r4, #0x00000020 @ val 0x4107b020 - and r0, r9, r3 - teq r0, r4 @ ARM 11MPCore? + orr r4, r4, #0x00000020 @ val 0x4100b020 + teq r3, r4 @ ARM 11MPCore? moveq pc, lr @ yes, assume SMP mrc p15, 0, r0, c0, c0, 5 @ read MPIDR - tst r0, #1 << 31 - movne pc, lr @ bit 31 => SMP + and r0, r0, #0xc0000000 @ multiprocessing extensions and + teq r0, #0x80000000 @ not part of a uniprocessor system? + moveq pc, lr @ yes, assume SMP __fixup_smp_on_up: adr r0, 1f @@ -417,18 +411,7 @@ __fixup_smp_on_up: sub r3, r0, r3 add r4, r4, r3 add r5, r5, r3 -2: cmp r4, r5 - movhs pc, lr - ldmia r4!, {r0, r6} - ARM( str r6, [r0, r3] ) - THUMB( add r0, r0, r3 ) -#ifdef __ARMEB__ - THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. -#endif - THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords - THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. - THUMB( strh r6, [r0] ) - b 2b + b __do_fixup_smp_on_up ENDPROC(__fixup_smp) .align @@ -442,7 +425,31 @@ smp_on_up: ALT_SMP(.long 1) ALT_UP(.long 0) .popsection +#endif + .text +__do_fixup_smp_on_up: + cmp r4, r5 + movhs pc, lr + ldmia r4!, {r0, r6} + ARM( str r6, [r0, r3] ) + THUMB( add r0, r0, r3 ) +#ifdef __ARMEB__ + THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. #endif + THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords + THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. + THUMB( strh r6, [r0] ) + b __do_fixup_smp_on_up +ENDPROC(__do_fixup_smp_on_up) + +ENTRY(fixup_smp) + stmfd sp!, {r4 - r6, lr} + mov r4, r0 + add r5, r0, r1 + mov r3, #0 + bl __do_fixup_smp_on_up + ldmfd sp!, {r4 - r6, pc} +ENDPROC(fixup_smp) #include "head-common.S" diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index c9f3f0467570..44b84fe6e1b0 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -137,11 +137,10 @@ static u8 get_debug_arch(void) u32 didr; /* Do we implement the extended CPUID interface? */ - if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { - pr_warning("CPUID feature registers not supported. " - "Assuming v6 debug is present.\n"); + if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf), + "CPUID feature registers not supported. " + "Assuming v6 debug is present.\n")) return ARM_DEBUG_ARCH_V6; - } ARM_DBG_READ(c0, 0, didr); return (didr >> 16) & 0xf; @@ -152,6 +151,12 @@ u8 arch_get_debug_arch(void) return debug_arch; } +static int debug_arch_supported(void) +{ + u8 arch = get_debug_arch(); + return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14; +} + /* Determine number of BRP register available. */ static int get_num_brp_resources(void) { @@ -268,6 +273,9 @@ out: int hw_breakpoint_slots(int type) { + if (!debug_arch_supported()) + return 0; + /* * We can be called early, so don't rely on * our static variables being initialised. @@ -828,20 +836,33 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, /* * One-time initialisation. */ -static void reset_ctrl_regs(void *unused) +static void reset_ctrl_regs(void *info) { - int i; + int i, cpu = smp_processor_id(); + u32 dbg_power; + cpumask_t *cpumask = info; /* * v7 debug contains save and restore registers so that debug state - * can be maintained across low-power modes without leaving - * the debug logic powered up. It is IMPLEMENTATION DEFINED whether - * we can write to the debug registers out of reset, so we must - * unlock the OS Lock Access Register to avoid taking undefined - * instruction exceptions later on. + * can be maintained across low-power modes without leaving the debug + * logic powered up. It is IMPLEMENTATION DEFINED whether we can access + * the debug registers out of reset, so we must unlock the OS Lock + * Access Register to avoid taking undefined instruction exceptions + * later on. */ if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) { /* + * Ensure sticky power-down is clear (i.e. debug logic is + * powered up). + */ + asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power)); + if ((dbg_power & 0x1) == 0) { + pr_warning("CPU %d debug is powered down!\n", cpu); + cpumask_or(cpumask, cpumask, cpumask_of(cpu)); + return; + } + + /* * Unconditionally clear the lock by writing a value * other than 0xC5ACCE55 to the access register. */ @@ -879,10 +900,11 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = { static int __init arch_hw_breakpoint_init(void) { u32 dscr; + cpumask_t cpumask = { CPU_BITS_NONE }; debug_arch = get_debug_arch(); - if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) { + if (!debug_arch_supported()) { pr_info("debug architecture 0x%x unsupported.\n", debug_arch); return 0; } @@ -899,18 +921,24 @@ static int __init arch_hw_breakpoint_init(void) pr_info("%d breakpoint(s) reserved for watchpoint " "single-step.\n", core_num_reserved_brps); + /* + * Reset the breakpoint resources. We assume that a halting + * debugger will leave the world in a nice state for us. + */ + on_each_cpu(reset_ctrl_regs, &cpumask, 1); + if (!cpumask_empty(&cpumask)) { + core_num_brps = 0; + core_num_reserved_brps = 0; + core_num_wrps = 0; + return 0; + } + ARM_DBG_READ(c1, 0, dscr); if (dscr & ARM_DSCR_HDBGEN) { + max_watchpoint_len = 4; pr_warning("halting debug mode enabled. Assuming maximum " - "watchpoint size of 4 bytes."); + "watchpoint size of %u bytes.", max_watchpoint_len); } else { - /* - * Reset the breakpoint resources. We assume that a halting - * debugger will leave the world in a nice state for us. - */ - smp_call_function(reset_ctrl_regs, NULL, 1); - reset_ctrl_regs(NULL); - /* Work out the maximum supported watchpoint length. */ max_watchpoint_len = get_max_wp_len(); pr_info("maximum watchpoint size is %u bytes.\n", diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 28536e352deb..3535d3793e65 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -179,14 +179,21 @@ int __init arch_probe_nr_irqs(void) #ifdef CONFIG_HOTPLUG_CPU -static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) +static bool migrate_one_irq(struct irq_data *d) { - pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->irq_data.node, cpu); + unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask); + bool ret = false; - raw_spin_lock_irq(&desc->lock); - desc->irq_data.chip->irq_set_affinity(&desc->irq_data, - cpumask_of(cpu), false); - raw_spin_unlock_irq(&desc->lock); + if (cpu >= nr_cpu_ids) { + cpu = cpumask_any(cpu_online_mask); + ret = true; + } + + pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu); + + d->chip->irq_set_affinity(d, cpumask_of(cpu), true); + + return ret; } /* @@ -198,25 +205,30 @@ void migrate_irqs(void) { unsigned int i, cpu = smp_processor_id(); struct irq_desc *desc; + unsigned long flags; + + local_irq_save(flags); for_each_irq_desc(i, desc) { struct irq_data *d = &desc->irq_data; + bool affinity_broken = false; - if (d->node == cpu) { - unsigned int newcpu = cpumask_any_and(d->affinity, - cpu_online_mask); - if (newcpu >= nr_cpu_ids) { - if (printk_ratelimit()) - printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n", - i, cpu); + raw_spin_lock(&desc->lock); + do { + if (desc->action == NULL) + break; - cpumask_setall(d->affinity); - newcpu = cpumask_any_and(d->affinity, - cpu_online_mask); - } + if (d->node != cpu) + break; - route_irq(desc, i, newcpu); - } + affinity_broken = migrate_one_irq(d); + } while (0); + raw_spin_unlock(&desc->lock); + + if (affinity_broken && printk_ratelimit()) + pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu); } + + local_irq_restore(flags); } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c index 2c1f0050c9c4..8f6ed43861f1 100644 --- a/arch/arm/kernel/kprobes-decode.c +++ b/arch/arm/kernel/kprobes-decode.c @@ -1437,7 +1437,7 @@ arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) return space_cccc_1100_010x(insn, asi); - } else if ((insn & 0x0e000000) == 0x0c400000) { + } else if ((insn & 0x0e000000) == 0x0c000000) { return space_cccc_110x(insn, asi); diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index 2cfe8161b478..6fcf22cf385c 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -22,6 +22,7 @@ #include <asm/pgtable.h> #include <asm/sections.h> +#include <asm/smp_plat.h> #include <asm/unwind.h> #ifdef CONFIG_XIP_KERNEL @@ -75,6 +76,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { unsigned long loc; Elf32_Sym *sym; + const char *symname; s32 offset; #ifdef CONFIG_THUMB2_KERNEL u32 upper, lower, sign, j1, j2; @@ -82,18 +84,18 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, offset = ELF32_R_SYM(rel->r_info); if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { - printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n", + pr_err("%s: section %u reloc %u: bad relocation sym offset\n", module->name, relindex, i); return -ENOEXEC; } sym = ((Elf32_Sym *)symsec->sh_addr) + offset; + symname = strtab + sym->st_name; if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { - printk(KERN_ERR "%s: out of bounds relocation, " - "section %d reloc %d offset %d size %d\n", - module->name, relindex, i, rel->r_offset, - dstsec->sh_size); + pr_err("%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n", + module->name, relindex, i, symname, + rel->r_offset, dstsec->sh_size); return -ENOEXEC; } @@ -119,10 +121,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, if (offset & 3 || offset <= (s32)0xfe000000 || offset >= (s32)0x02000000) { - printk(KERN_ERR - "%s: relocation out of range, section " - "%d reloc %d sym '%s'\n", module->name, - relindex, i, strtab + sym->st_name); + pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", + module->name, relindex, i, symname, + ELF32_R_TYPE(rel->r_info), loc, + sym->st_value); return -ENOEXEC; } @@ -195,10 +197,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, 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); + pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", + module->name, relindex, i, symname, + ELF32_R_TYPE(rel->r_info), loc, + sym->st_value); return -ENOEXEC; } @@ -268,12 +270,28 @@ struct mod_unwind_map { const Elf_Shdr *txt_sec; }; +static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr, + const Elf_Shdr *sechdrs, const char *name) +{ + const Elf_Shdr *s, *se; + const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + + for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) + if (strcmp(name, secstrs + s->sh_name) == 0) + return s; + + return NULL; +} + +extern void fixup_smp(const void *, unsigned long); + int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) { + const Elf_Shdr * __maybe_unused s = NULL; #ifdef CONFIG_ARM_UNWIND const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; + const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; struct mod_unwind_map maps[ARM_SEC_MAX]; int i; @@ -315,6 +333,9 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, maps[i].txt_sec->sh_addr, maps[i].txt_sec->sh_size); #endif + s = find_mod_section(hdr, sechdrs, ".alt.smp.init"); + if (s && !is_smp()) + fixup_smp((void *)s->sh_addr, s->sh_size); return 0; } diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 5efa2647a2fb..d150ad1ccb5d 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -700,7 +700,7 @@ user_backtrace(struct frame_tail __user *tail, * Frame pointers should strictly progress back up the stack * (towards higher addresses). */ - if (tail >= buftail.fp) + if (tail + 1 >= buftail.fp) return NULL; return buftail.fp - 1; diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index b8af96ea62e6..2c79eec19262 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -97,28 +97,34 @@ set_irq_affinity(int irq, irq, cpu); return err; #else - return 0; + return -EINVAL; #endif } static int init_cpu_pmu(void) { - int i, err = 0; + int i, irqs, err = 0; struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU]; - if (!pdev) { - err = -ENODEV; - goto out; - } + if (!pdev) + return -ENODEV; + + irqs = pdev->num_resources; + + /* + * If we have a single PMU interrupt that we can't shift, assume that + * we're running on a uniprocessor machine and continue. + */ + if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0))) + return 0; - for (i = 0; i < pdev->num_resources; ++i) { + for (i = 0; i < irqs; ++i) { err = set_irq_affinity(platform_get_irq(pdev, i), i); if (err) break; } -out: return err; } diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 19c6816db61e..2bf27f364d09 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -26,8 +26,6 @@ #include <asm/system.h> #include <asm/traps.h> -#include "ptrace.h" - #define REG_PC 15 #define REG_PSR 16 /* @@ -184,389 +182,12 @@ put_user_reg(struct task_struct *task, int offset, long data) return ret; } -static inline int -read_u32(struct task_struct *task, unsigned long addr, u32 *res) -{ - int ret; - - ret = access_process_vm(task, addr, res, sizeof(*res), 0); - - return ret == sizeof(*res) ? 0 : -EIO; -} - -static inline int -read_instr(struct task_struct *task, unsigned long addr, u32 *res) -{ - int ret; - - if (addr & 1) { - u16 val; - ret = access_process_vm(task, addr & ~1, &val, sizeof(val), 0); - ret = ret == sizeof(val) ? 0 : -EIO; - *res = val; - } else { - u32 val; - ret = access_process_vm(task, addr & ~3, &val, sizeof(val), 0); - ret = ret == sizeof(val) ? 0 : -EIO; - *res = val; - } - return ret; -} - -/* - * Get value of register `rn' (in the instruction) - */ -static unsigned long -ptrace_getrn(struct task_struct *child, unsigned long insn) -{ - unsigned int reg = (insn >> 16) & 15; - unsigned long val; - - val = get_user_reg(child, reg); - if (reg == 15) - val += 8; - - return val; -} - -/* - * Get value of operand 2 (in an ALU instruction) - */ -static unsigned long -ptrace_getaluop2(struct task_struct *child, unsigned long insn) -{ - unsigned long val; - int shift; - int type; - - if (insn & 1 << 25) { - val = insn & 255; - shift = (insn >> 8) & 15; - type = 3; - } else { - val = get_user_reg (child, insn & 15); - - if (insn & (1 << 4)) - shift = (int)get_user_reg (child, (insn >> 8) & 15); - else - shift = (insn >> 7) & 31; - - type = (insn >> 5) & 3; - } - - switch (type) { - case 0: val <<= shift; break; - case 1: val >>= shift; break; - case 2: - val = (((signed long)val) >> shift); - break; - case 3: - val = (val >> shift) | (val << (32 - shift)); - break; - } - return val; -} - -/* - * Get value of operand 2 (in a LDR instruction) - */ -static unsigned long -ptrace_getldrop2(struct task_struct *child, unsigned long insn) -{ - unsigned long val; - int shift; - int type; - - val = get_user_reg(child, insn & 15); - shift = (insn >> 7) & 31; - type = (insn >> 5) & 3; - - switch (type) { - case 0: val <<= shift; break; - case 1: val >>= shift; break; - case 2: - val = (((signed long)val) >> shift); - break; - case 3: - val = (val >> shift) | (val << (32 - shift)); - break; - } - return val; -} - -#define OP_MASK 0x01e00000 -#define OP_AND 0x00000000 -#define OP_EOR 0x00200000 -#define OP_SUB 0x00400000 -#define OP_RSB 0x00600000 -#define OP_ADD 0x00800000 -#define OP_ADC 0x00a00000 -#define OP_SBC 0x00c00000 -#define OP_RSC 0x00e00000 -#define OP_ORR 0x01800000 -#define OP_MOV 0x01a00000 -#define OP_BIC 0x01c00000 -#define OP_MVN 0x01e00000 - -static unsigned long -get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn) -{ - u32 alt = 0; - - switch (insn & 0x0e000000) { - case 0x00000000: - case 0x02000000: { - /* - * data processing - */ - long aluop1, aluop2, ccbit; - - if ((insn & 0x0fffffd0) == 0x012fff10) { - /* - * bx or blx - */ - alt = get_user_reg(child, insn & 15); - break; - } - - - if ((insn & 0xf000) != 0xf000) - break; - - aluop1 = ptrace_getrn(child, insn); - aluop2 = ptrace_getaluop2(child, insn); - ccbit = get_user_reg(child, REG_PSR) & PSR_C_BIT ? 1 : 0; - - switch (insn & OP_MASK) { - case OP_AND: alt = aluop1 & aluop2; break; - case OP_EOR: alt = aluop1 ^ aluop2; break; - case OP_SUB: alt = aluop1 - aluop2; break; - case OP_RSB: alt = aluop2 - aluop1; break; - case OP_ADD: alt = aluop1 + aluop2; break; - case OP_ADC: alt = aluop1 + aluop2 + ccbit; break; - case OP_SBC: alt = aluop1 - aluop2 + ccbit; break; - case OP_RSC: alt = aluop2 - aluop1 + ccbit; break; - case OP_ORR: alt = aluop1 | aluop2; break; - case OP_MOV: alt = aluop2; break; - case OP_BIC: alt = aluop1 & ~aluop2; break; - case OP_MVN: alt = ~aluop2; break; - } - break; - } - - case 0x04000000: - case 0x06000000: - /* - * ldr - */ - if ((insn & 0x0010f000) == 0x0010f000) { - unsigned long base; - - base = ptrace_getrn(child, insn); - if (insn & 1 << 24) { - long aluop2; - - if (insn & 0x02000000) - aluop2 = ptrace_getldrop2(child, insn); - else - aluop2 = insn & 0xfff; - - if (insn & 1 << 23) - base += aluop2; - else - base -= aluop2; - } - read_u32(child, base, &alt); - } - break; - - case 0x08000000: - /* - * ldm - */ - if ((insn & 0x00108000) == 0x00108000) { - unsigned long base; - unsigned int nr_regs; - - if (insn & (1 << 23)) { - nr_regs = hweight16(insn & 65535) << 2; - - if (!(insn & (1 << 24))) - nr_regs -= 4; - } else { - if (insn & (1 << 24)) - nr_regs = -4; - else - nr_regs = 0; - } - - base = ptrace_getrn(child, insn); - - read_u32(child, base + nr_regs, &alt); - break; - } - break; - - case 0x0a000000: { - /* - * bl or b - */ - signed long displ; - /* It's a branch/branch link: instead of trying to - * figure out whether the branch will be taken or not, - * we'll put a breakpoint at both locations. This is - * simpler, more reliable, and probably not a whole lot - * slower than the alternative approach of emulating the - * branch. - */ - displ = (insn & 0x00ffffff) << 8; - displ = (displ >> 6) + 8; - if (displ != 0 && displ != 4) - alt = pc + displ; - } - break; - } - - return alt; -} - -static int -swap_insn(struct task_struct *task, unsigned long addr, - void *old_insn, void *new_insn, int size) -{ - int ret; - - ret = access_process_vm(task, addr, old_insn, size, 0); - if (ret == size) - ret = access_process_vm(task, addr, new_insn, size, 1); - return ret; -} - -static void -add_breakpoint(struct task_struct *task, struct debug_info *dbg, unsigned long addr) -{ - int nr = dbg->nsaved; - - if (nr < 2) { - u32 new_insn = BREAKINST_ARM; - int res; - - res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4); - - if (res == 4) { - dbg->bp[nr].address = addr; - dbg->nsaved += 1; - } - } else - printk(KERN_ERR "ptrace: too many breakpoints\n"); -} - -/* - * Clear one breakpoint in the user program. We copy what the hardware - * does and use bit 0 of the address to indicate whether this is a Thumb - * breakpoint or an ARM breakpoint. - */ -static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp) -{ - unsigned long addr = bp->address; - union debug_insn old_insn; - int ret; - - if (addr & 1) { - ret = swap_insn(task, addr & ~1, &old_insn.thumb, - &bp->insn.thumb, 2); - - if (ret != 2 || old_insn.thumb != BREAKINST_THUMB) - printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at " - "0x%08lx (0x%04x)\n", task->comm, - task_pid_nr(task), addr, old_insn.thumb); - } else { - ret = swap_insn(task, addr & ~3, &old_insn.arm, - &bp->insn.arm, 4); - - if (ret != 4 || old_insn.arm != BREAKINST_ARM) - printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at " - "0x%08lx (0x%08x)\n", task->comm, - task_pid_nr(task), addr, old_insn.arm); - } -} - -void ptrace_set_bpt(struct task_struct *child) -{ - struct pt_regs *regs; - unsigned long pc; - u32 insn; - int res; - - regs = task_pt_regs(child); - pc = instruction_pointer(regs); - - if (thumb_mode(regs)) { - printk(KERN_WARNING "ptrace: can't handle thumb mode\n"); - return; - } - - res = read_instr(child, pc, &insn); - if (!res) { - struct debug_info *dbg = &child->thread.debug; - unsigned long alt; - - dbg->nsaved = 0; - - alt = get_branch_address(child, pc, insn); - if (alt) - add_breakpoint(child, dbg, alt); - - /* - * Note that we ignore the result of setting the above - * breakpoint since it may fail. When it does, this is - * not so much an error, but a forewarning that we may - * be receiving a prefetch abort shortly. - * - * If we don't set this breakpoint here, then we can - * lose control of the thread during single stepping. - */ - if (!alt || predicate(insn) != PREDICATE_ALWAYS) - add_breakpoint(child, dbg, pc + 4); - } -} - -/* - * Ensure no single-step breakpoint is pending. Returns non-zero - * value if child was being single-stepped. - */ -void ptrace_cancel_bpt(struct task_struct *child) -{ - int i, nsaved = child->thread.debug.nsaved; - - child->thread.debug.nsaved = 0; - - if (nsaved > 2) { - printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved); - nsaved = 2; - } - - for (i = 0; i < nsaved; i++) - clear_breakpoint(child, &child->thread.debug.bp[i]); -} - -void user_disable_single_step(struct task_struct *task) -{ - task->ptrace &= ~PT_SINGLESTEP; - ptrace_cancel_bpt(task); -} - -void user_enable_single_step(struct task_struct *task) -{ - task->ptrace |= PT_SINGLESTEP; -} - /* * Called by kernel/ptrace.c when detaching.. */ void ptrace_disable(struct task_struct *child) { - user_disable_single_step(child); + /* Nothing to do. */ } /* @@ -576,8 +197,6 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) { siginfo_t info; - ptrace_cancel_bpt(tsk); - info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; @@ -996,10 +615,10 @@ static int ptrace_gethbpregs(struct task_struct *tsk, long num, while (!(arch_ctrl.len & 0x1)) arch_ctrl.len >>= 1; - if (idx & 0x1) - reg = encode_ctrl_reg(arch_ctrl); - else + if (num & 0x1) reg = bp->attr.bp_addr; + else + reg = encode_ctrl_reg(arch_ctrl); } put: diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h deleted file mode 100644 index 3926605b82ea..000000000000 --- a/arch/arm/kernel/ptrace.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * linux/arch/arm/kernel/ptrace.h - * - * Copyright (C) 2000-2003 Russell King - * - * 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/ptrace.h> - -extern void ptrace_cancel_bpt(struct task_struct *); -extern void ptrace_set_bpt(struct task_struct *); -extern void ptrace_break(struct task_struct *, struct pt_regs *); - -/* - * Send SIGTRAP if we're single-stepping - */ -static inline void single_step_trap(struct task_struct *task) -{ - if (task->ptrace & PT_SINGLESTEP) { - ptrace_cancel_bpt(task); - send_sig(SIGTRAP, task, 1); - } -} - -static inline void single_step_clear(struct task_struct *task) -{ - if (task->ptrace & PT_SINGLESTEP) - ptrace_cancel_bpt(task); -} - -static inline void single_step_set(struct task_struct *task) -{ - if (task->ptrace & PT_SINGLESTEP) - ptrace_set_bpt(task); -} diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c index df246da4ceca..0b13a72f855d 100644 --- a/arch/arm/kernel/return_address.c +++ b/arch/arm/kernel/return_address.c @@ -9,6 +9,7 @@ * the Free Software Foundation. */ #include <linux/module.h> +#include <linux/ftrace.h> #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) #include <linux/sched.h> diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 420b8d6485d6..db2382853450 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -226,8 +226,8 @@ int cpu_architecture(void) * Register 0 and check for VMSAv7 or PMSAv7 */ asm("mrc p15, 0, %0, c0, c1, 4" : "=r" (mmfr0)); - if ((mmfr0 & 0x0000000f) == 0x00000003 || - (mmfr0 & 0x000000f0) == 0x00000030) + if ((mmfr0 & 0x0000000f) >= 0x00000003 || + (mmfr0 & 0x000000f0) >= 0x00000030) cpu_arch = CPU_ARCH_ARMv7; else if ((mmfr0 & 0x0000000f) == 0x00000002 || (mmfr0 & 0x000000f0) == 0x00000020) @@ -308,7 +308,44 @@ static void __init cacheid_init(void) * already provide the required functionality. */ extern struct proc_info_list *lookup_processor_type(unsigned int); -extern struct machine_desc *lookup_machine_type(unsigned int); + +static void __init early_print(const char *str, ...) +{ + extern void printascii(const char *); + char buf[256]; + va_list ap; + + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + +#ifdef CONFIG_DEBUG_LL + printascii(buf); +#endif + printk("%s", buf); +} + +static struct machine_desc * __init lookup_machine_type(unsigned int type) +{ + extern struct machine_desc __arch_info_begin[], __arch_info_end[]; + struct machine_desc *p; + + for (p = __arch_info_begin; p < __arch_info_end; p++) + if (type == p->nr) + return p; + + early_print("\n" + "Error: unrecognized/unsupported machine ID (r1 = 0x%08x).\n\n" + "Available machine support:\n\nID (hex)\tNAME\n", type); + + for (p = __arch_info_begin; p < __arch_info_end; p++) + early_print("%08x\t%s\n", p->nr, p->name); + + early_print("\nPlease check your kernel config and/or bootloader.\n"); + + while (true) + /* can't use cpu_relax() here as it may require MMU setup */; +} static void __init feat_v6_fixup(void) { diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 907d5a620bca..cb8398317644 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -20,7 +20,6 @@ #include <asm/unistd.h> #include <asm/vfp.h> -#include "ptrace.h" #include "signal.h" #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) @@ -348,8 +347,6 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) if (restore_sigframe(regs, frame)) goto badframe; - single_step_trap(current); - return regs->ARM_r0; badframe: @@ -383,8 +380,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) goto badframe; - single_step_trap(current); - return regs->ARM_r0; badframe: @@ -474,7 +469,9 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, unsigned long handler = (unsigned long)ka->sa.sa_handler; unsigned long retcode; int thumb = 0; - unsigned long cpsr = regs->ARM_cpsr & ~PSR_f; + unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); + + cpsr |= PSR_ENDSTATE; /* * Maybe we need to deliver a 32-bit signal to a 26-bit task. @@ -704,8 +701,6 @@ static void do_signal(struct pt_regs *regs, int syscall) if (try_to_freeze()) goto no_signal; - single_step_clear(current); - signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { sigset_t *oldset; @@ -724,7 +719,6 @@ static void do_signal(struct pt_regs *regs, int syscall) if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); } - single_step_set(current); return; } @@ -770,7 +764,6 @@ static void do_signal(struct pt_regs *regs, int syscall) sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } - single_step_set(current); } asmlinkage void diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S new file mode 100644 index 000000000000..bfad698a02e7 --- /dev/null +++ b/arch/arm/kernel/sleep.S @@ -0,0 +1,134 @@ +#include <linux/linkage.h> +#include <linux/threads.h> +#include <asm/asm-offsets.h> +#include <asm/assembler.h> +#include <asm/glue-cache.h> +#include <asm/glue-proc.h> +#include <asm/system.h> + .text + +/* + * Save CPU state for a suspend + * r1 = v:p offset + * r3 = virtual return function + * Note: sp is decremented to allocate space for CPU state on stack + * r0-r3,r9,r10,lr corrupted + */ +ENTRY(cpu_suspend) + mov r9, lr +#ifdef MULTI_CPU + ldr r10, =processor + mov r2, sp @ current virtual SP + ldr r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state + ldr ip, [r10, #CPU_DO_RESUME] @ virtual resume function + sub sp, sp, r0 @ allocate CPU state on stack + mov r0, sp @ save pointer + add ip, ip, r1 @ convert resume fn to phys + stmfd sp!, {r1, r2, r3, ip} @ save v:p, virt SP, retfn, phys resume fn + ldr r3, =sleep_save_sp + add r2, sp, r1 @ convert SP to phys +#ifdef CONFIG_SMP + ALT_SMP(mrc p15, 0, lr, c0, c0, 5) + ALT_UP(mov lr, #0) + and lr, lr, #15 + str r2, [r3, lr, lsl #2] @ save phys SP +#else + str r2, [r3] @ save phys SP +#endif + mov lr, pc + ldr pc, [r10, #CPU_DO_SUSPEND] @ save CPU state +#else + mov r2, sp @ current virtual SP + ldr r0, =cpu_suspend_size + sub sp, sp, r0 @ allocate CPU state on stack + mov r0, sp @ save pointer + stmfd sp!, {r1, r2, r3} @ save v:p, virt SP, return fn + ldr r3, =sleep_save_sp + add r2, sp, r1 @ convert SP to phys +#ifdef CONFIG_SMP + ALT_SMP(mrc p15, 0, lr, c0, c0, 5) + ALT_UP(mov lr, #0) + and lr, lr, #15 + str r2, [r3, lr, lsl #2] @ save phys SP +#else + str r2, [r3] @ save phys SP +#endif + bl cpu_do_suspend +#endif + + @ flush data cache +#ifdef MULTI_CACHE + ldr r10, =cpu_cache + mov lr, r9 + ldr pc, [r10, #CACHE_FLUSH_KERN_ALL] +#else + mov lr, r9 + b __cpuc_flush_kern_all +#endif +ENDPROC(cpu_suspend) + .ltorg + +/* + * r0 = control register value + * r1 = v:p offset (preserved by cpu_do_resume) + * r2 = phys page table base + * r3 = L1 section flags + */ +ENTRY(cpu_resume_mmu) + adr r4, cpu_resume_turn_mmu_on + mov r4, r4, lsr #20 + orr r3, r3, r4, lsl #20 + ldr r5, [r2, r4, lsl #2] @ save old mapping + str r3, [r2, r4, lsl #2] @ setup 1:1 mapping for mmu code + sub r2, r2, r1 + ldr r3, =cpu_resume_after_mmu + bic r1, r0, #CR_C @ ensure D-cache is disabled + b cpu_resume_turn_mmu_on +ENDPROC(cpu_resume_mmu) + .ltorg + .align 5 +cpu_resume_turn_mmu_on: + mcr p15, 0, r1, c1, c0, 0 @ turn on MMU, I-cache, etc + mrc p15, 0, r1, c0, c0, 0 @ read id reg + mov r1, r1 + mov r1, r1 + mov pc, r3 @ jump to virtual address +ENDPROC(cpu_resume_turn_mmu_on) +cpu_resume_after_mmu: + str r5, [r2, r4, lsl #2] @ restore old mapping + mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache + mov pc, lr +ENDPROC(cpu_resume_after_mmu) + +/* + * Note: Yes, part of the following code is located into the .data section. + * This is to allow sleep_save_sp to be accessed with a relative load + * while we can't rely on any MMU translation. We could have put + * sleep_save_sp in the .text section as well, but some setups might + * insist on it to be truly read-only. + */ + .data + .align +ENTRY(cpu_resume) +#ifdef CONFIG_SMP + adr r0, sleep_save_sp + ALT_SMP(mrc p15, 0, r1, c0, c0, 5) + ALT_UP(mov r1, #0) + and r1, r1, #15 + ldr r0, [r0, r1, lsl #2] @ stack phys addr +#else + ldr r0, sleep_save_sp @ stack phys addr +#endif + msr cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off +#ifdef MULTI_CPU + ldmia r0!, {r1, sp, lr, pc} @ load v:p, stack, return fn, resume fn +#else + ldmia r0!, {r1, sp, lr} @ load v:p, stack, return fn + b cpu_do_resume +#endif +ENDPROC(cpu_resume) + +sleep_save_sp: + .rept CONFIG_NR_CPUS + .long 0 @ preserve stack phys ptr here + .endr diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c index 9ab4149bd983..a1e757c3439b 100644 --- a/arch/arm/kernel/smp_scu.c +++ b/arch/arm/kernel/smp_scu.c @@ -50,3 +50,26 @@ void __init scu_enable(void __iomem *scu_base) */ flush_cache_all(); } + +/* + * Set the executing CPUs power mode as defined. This will be in + * preparation for it executing a WFI instruction. + * + * This function must be called with preemption disabled, and as it + * has the side effect of disabling coherency, caches must have been + * flushed. Interrupts must also have been disabled. + */ +int scu_power_mode(void __iomem *scu_base, unsigned int mode) +{ + unsigned int val; + int cpu = smp_processor_id(); + + if (mode > 3 || mode == 1 || cpu > 3) + return -EINVAL; + + val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; + val |= mode; + __raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu); + + return 0; +} diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index fd9156698ab9..60636f499cb3 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -36,6 +36,7 @@ static void twd_set_mode(enum clock_event_mode mode, /* timer load already set up */ ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_PERIODIC; + __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); break; case CLOCK_EVT_MODE_ONESHOT: /* period set, and timer enabled in 'next_event' hook */ @@ -81,7 +82,7 @@ int twd_timer_ack(void) static void __cpuinit twd_calibrate_rate(void) { - unsigned long load, count; + unsigned long count; u64 waitjiffies; /* @@ -116,10 +117,6 @@ static void __cpuinit twd_calibrate_rate(void) printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000, (twd_timer_rate / 1000000) % 100); } - - load = twd_timer_rate / HZ; - - __raw_writel(load, twd_base + TWD_TIMER_LOAD); } /* diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index ee57640ba2bb..21ac43f1c2d0 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -23,6 +23,7 @@ #include <linux/kexec.h> #include <linux/delay.h> #include <linux/init.h> +#include <linux/sched.h> #include <asm/atomic.h> #include <asm/cacheflush.h> @@ -32,7 +33,6 @@ #include <asm/unwind.h> #include <asm/tls.h> -#include "ptrace.h" #include "signal.h" static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; @@ -256,7 +256,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt return ret; } -DEFINE_SPINLOCK(die_lock); +static DEFINE_SPINLOCK(die_lock); /* * This function is protected against re-entrancy. diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 86b66f3f2031..61462790757f 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -21,6 +21,12 @@ #define ARM_CPU_KEEP(x) #endif +#if defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK) +#define ARM_EXIT_KEEP(x) x +#else +#define ARM_EXIT_KEEP(x) +#endif + OUTPUT_ARCH(arm) ENTRY(stext) @@ -43,6 +49,7 @@ SECTIONS _sinittext = .; HEAD_TEXT INIT_TEXT + ARM_EXIT_KEEP(EXIT_TEXT) _einittext = .; ARM_CPU_DISCARD(PROC_INFO) __arch_info_begin = .; @@ -67,6 +74,7 @@ SECTIONS #ifndef CONFIG_XIP_KERNEL __init_begin = _stext; INIT_DATA + ARM_EXIT_KEEP(EXIT_DATA) #endif } @@ -162,6 +170,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); __init_begin = .; INIT_DATA + ARM_EXIT_KEEP(EXIT_DATA) . = ALIGN(PAGE_SIZE); __init_end = .; #endif @@ -247,6 +256,8 @@ SECTIONS } #endif + NOTES + BSS_SECTION(0, 0, 0) _end = .; diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c index 0a99b3cedd7a..17f7d9b32142 100644 --- a/arch/arm/mach-at91/board-snapper9260.c +++ b/arch/arm/mach-at91/board-snapper9260.c @@ -153,6 +153,7 @@ static struct i2c_board_info __initdata snapper9260_i2c_devices[] = { { /* RTC */ I2C_BOARD_INFO("isl1208", 0x6f), + .irq = gpio_to_irq(AT91_PIN_PA31), }, }; diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index bfdd8ab26dc8..ddeb64536756 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -220,15 +220,8 @@ extern void at91_gpio_resume(void); #define gpio_set_value __gpio_set_value #define gpio_cansleep __gpio_cansleep -static inline int gpio_to_irq(unsigned gpio) -{ - return gpio; -} - -static inline int irq_to_gpio(unsigned irq) -{ - return irq; -} +#define gpio_to_irq(gpio) (gpio) +#define irq_to_gpio(irq) (irq) #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c index 343de73161fa..4a68c2b1ec11 100644 --- a/arch/arm/mach-davinci/cpufreq.c +++ b/arch/arm/mach-davinci/cpufreq.c @@ -132,7 +132,7 @@ out: return ret; } -static int __init davinci_cpu_init(struct cpufreq_policy *policy) +static int davinci_cpu_init(struct cpufreq_policy *policy) { int result = 0; struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data; diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 9eec63070e0c..beda8a4133a0 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -480,8 +480,15 @@ static struct platform_device da850_mcasp_device = { .resource = da850_mcasp_resources, }; +struct platform_device davinci_pcm_device = { + .name = "davinci-pcm-audio", + .id = -1, +}; + void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata) { + platform_device_register(&davinci_pcm_device); + /* DA830/OMAP-L137 has 3 instances of McASP */ if (cpu_is_davinci_da830() && id == 1) { da830_mcasp1_device.dev.platform_data = pdata; diff --git a/arch/arm/mach-davinci/gpio-tnetv107x.c b/arch/arm/mach-davinci/gpio-tnetv107x.c index d10298620e2c..3fa3e2867e19 100644 --- a/arch/arm/mach-davinci/gpio-tnetv107x.c +++ b/arch/arm/mach-davinci/gpio-tnetv107x.c @@ -58,7 +58,7 @@ static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset) spin_lock_irqsave(&ctlr->lock, flags); - gpio_reg_set_bit(®s->enable, gpio); + gpio_reg_set_bit(regs->enable, gpio); spin_unlock_irqrestore(&ctlr->lock, flags); @@ -74,7 +74,7 @@ static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset) spin_lock_irqsave(&ctlr->lock, flags); - gpio_reg_clear_bit(®s->enable, gpio); + gpio_reg_clear_bit(regs->enable, gpio); spin_unlock_irqrestore(&ctlr->lock, flags); } @@ -88,7 +88,7 @@ static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset) spin_lock_irqsave(&ctlr->lock, flags); - gpio_reg_set_bit(®s->direction, gpio); + gpio_reg_set_bit(regs->direction, gpio); spin_unlock_irqrestore(&ctlr->lock, flags); @@ -106,11 +106,11 @@ static int tnetv107x_gpio_dir_out(struct gpio_chip *chip, spin_lock_irqsave(&ctlr->lock, flags); if (value) - gpio_reg_set_bit(®s->data_out, gpio); + gpio_reg_set_bit(regs->data_out, gpio); else - gpio_reg_clear_bit(®s->data_out, gpio); + gpio_reg_clear_bit(regs->data_out, gpio); - gpio_reg_clear_bit(®s->direction, gpio); + gpio_reg_clear_bit(regs->direction, gpio); spin_unlock_irqrestore(&ctlr->lock, flags); @@ -124,7 +124,7 @@ static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset) unsigned gpio = chip->base + offset; int ret; - ret = gpio_reg_get_bit(®s->data_in, gpio); + ret = gpio_reg_get_bit(regs->data_in, gpio); return ret ? 1 : 0; } @@ -140,9 +140,9 @@ static void tnetv107x_gpio_set(struct gpio_chip *chip, spin_lock_irqsave(&ctlr->lock, flags); if (value) - gpio_reg_set_bit(®s->data_out, gpio); + gpio_reg_set_bit(regs->data_out, gpio); else - gpio_reg_clear_bit(®s->data_out, gpio); + gpio_reg_clear_bit(regs->data_out, gpio); spin_unlock_irqrestore(&ctlr->lock, flags); } diff --git a/arch/arm/mach-davinci/include/mach/clkdev.h b/arch/arm/mach-davinci/include/mach/clkdev.h index 730c49d1ebd8..14a504887189 100644 --- a/arch/arm/mach-davinci/include/mach/clkdev.h +++ b/arch/arm/mach-davinci/include/mach/clkdev.h @@ -1,6 +1,8 @@ #ifndef __MACH_CLKDEV_H #define __MACH_CLKDEV_H +struct clk; + static inline int __clk_get(struct clk *clk) { return 1; diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index ffdf87be2958..82079545adc4 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -838,7 +838,7 @@ EXPORT_SYMBOL(ep93xx_i2s_release); static struct resource ep93xx_ac97_resources[] = { { .start = EP93XX_AAC_PHYS_BASE, - .end = EP93XX_AAC_PHYS_BASE + 0xb0 - 1, + .end = EP93XX_AAC_PHYS_BASE + 0xac - 1, .flags = IORESOURCE_MEM, }, { diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index 4b0431652131..9969bb115f60 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -30,8 +30,13 @@ #include <linux/gpio.h> #include <linux/i2c.h> #include <linux/i2c-gpio.h> +#include <linux/spi/spi.h> + +#include <sound/cs4271.h> #include <mach/hardware.h> +#include <mach/fb.h> +#include <mach/ep93xx_spi.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -93,6 +98,83 @@ static void __init edb93xx_register_i2c(void) /************************************************************************* + * EDB93xx SPI peripheral handling + *************************************************************************/ +static struct cs4271_platform_data edb93xx_cs4271_data = { + .gpio_nreset = -EINVAL, /* filled in later */ +}; + +static int edb93xx_cs4271_hw_setup(struct spi_device *spi) +{ + return gpio_request_one(EP93XX_GPIO_LINE_EGPIO6, + GPIOF_OUT_INIT_HIGH, spi->modalias); +} + +static void edb93xx_cs4271_hw_cleanup(struct spi_device *spi) +{ + gpio_free(EP93XX_GPIO_LINE_EGPIO6); +} + +static void edb93xx_cs4271_hw_cs_control(struct spi_device *spi, int value) +{ + gpio_set_value(EP93XX_GPIO_LINE_EGPIO6, value); +} + +static struct ep93xx_spi_chip_ops edb93xx_cs4271_hw = { + .setup = edb93xx_cs4271_hw_setup, + .cleanup = edb93xx_cs4271_hw_cleanup, + .cs_control = edb93xx_cs4271_hw_cs_control, +}; + +static struct spi_board_info edb93xx_spi_board_info[] __initdata = { + { + .modalias = "cs4271", + .platform_data = &edb93xx_cs4271_data, + .controller_data = &edb93xx_cs4271_hw, + .max_speed_hz = 6000000, + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_3, + }, +}; + +static struct ep93xx_spi_info edb93xx_spi_info __initdata = { + .num_chipselect = ARRAY_SIZE(edb93xx_spi_board_info), +}; + +static void __init edb93xx_register_spi(void) +{ + if (machine_is_edb9301() || machine_is_edb9302()) + edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO1; + else if (machine_is_edb9302a() || machine_is_edb9307a()) + edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_H(2); + else if (machine_is_edb9315a()) + edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO14; + + ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info, + ARRAY_SIZE(edb93xx_spi_board_info)); +} + + +/************************************************************************* + * EDB93xx I2S + *************************************************************************/ +static int __init edb93xx_has_audio(void) +{ + return (machine_is_edb9301() || machine_is_edb9302() || + machine_is_edb9302a() || machine_is_edb9307a() || + machine_is_edb9315a()); +} + +static void __init edb93xx_register_i2s(void) +{ + if (edb93xx_has_audio()) { + ep93xx_register_i2s(); + } +} + + +/************************************************************************* * EDB93xx pwm *************************************************************************/ static void __init edb93xx_register_pwm(void) @@ -111,13 +193,47 @@ static void __init edb93xx_register_pwm(void) } +/************************************************************************* + * EDB93xx framebuffer + *************************************************************************/ +static struct ep93xxfb_mach_info __initdata edb93xxfb_info = { + .num_modes = EP93XXFB_USE_MODEDB, + .bpp = 16, + .flags = 0, +}; + +static int __init edb93xx_has_fb(void) +{ + /* These platforms have an ep93xx with video capability */ + return machine_is_edb9307() || machine_is_edb9307a() || + machine_is_edb9312() || machine_is_edb9315() || + machine_is_edb9315a(); +} + +static void __init edb93xx_register_fb(void) +{ + if (!edb93xx_has_fb()) + return; + + if (machine_is_edb9307a() || machine_is_edb9315a()) + edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0; + else + edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3; + + ep93xx_register_fb(&edb93xxfb_info); +} + + static void __init edb93xx_init_machine(void) { ep93xx_init_devices(); edb93xx_register_flash(); ep93xx_register_eth(&edb93xx_eth_data, 1); edb93xx_register_i2c(); + edb93xx_register_spi(); + edb93xx_register_i2s(); edb93xx_register_pwm(); + edb93xx_register_fb(); } diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c index f3dc76fdcea8..a889fa7c3ba1 100644 --- a/arch/arm/mach-ep93xx/gpio.c +++ b/arch/arm/mach-ep93xx/gpio.c @@ -61,7 +61,7 @@ static inline void ep93xx_gpio_int_mask(unsigned line) gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); } -void ep93xx_gpio_int_debounce(unsigned int irq, int enable) +static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable) { int line = irq_to_gpio(irq); int port = line >> 3; @@ -75,7 +75,6 @@ void ep93xx_gpio_int_debounce(unsigned int irq, int enable) __raw_writeb(gpio_int_debounce[port], EP93XX_GPIO_REG(int_debounce_register_offset[port])); } -EXPORT_SYMBOL(ep93xx_gpio_int_debounce); static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) { @@ -335,6 +334,20 @@ static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) local_irq_restore(flags); } +static int ep93xx_gpio_set_debounce(struct gpio_chip *chip, + unsigned offset, unsigned debounce) +{ + int gpio = chip->base + offset; + int irq = gpio_to_irq(gpio); + + if (irq < 0) + return -EINVAL; + + ep93xx_gpio_int_debounce(irq, debounce ? true : false); + + return 0; +} + static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) { struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); @@ -427,6 +440,25 @@ void __init ep93xx_gpio_init(void) { int i; - for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) - gpiochip_add(&ep93xx_gpio_banks[i].chip); + /* Set Ports C, D, E, G, and H for GPIO use */ + ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | + EP93XX_SYSCON_DEVCFG_GONK | + EP93XX_SYSCON_DEVCFG_EONIDE | + EP93XX_SYSCON_DEVCFG_GONIDE | + EP93XX_SYSCON_DEVCFG_HONIDE); + + for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) { + struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip; + + /* + * Ports A, B, and F support input debouncing when + * used as interrupts. + */ + if (!strcmp(chip->label, "A") || + !strcmp(chip->label, "B") || + !strcmp(chip->label, "F")) + chip->set_debounce = ep93xx_gpio_set_debounce; + + gpiochip_add(chip); + } } diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h index c991b149bdf2..c57152c231f1 100644 --- a/arch/arm/mach-ep93xx/include/mach/gpio.h +++ b/arch/arm/mach-ep93xx/include/mach/gpio.h @@ -99,8 +99,6 @@ /* maximum value for irq capable line identifiers */ #define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) -extern void ep93xx_gpio_int_debounce(unsigned int irq, int enable); - /* new generic GPIO API - see Documentation/gpio.txt */ #include <asm-generic/gpio.h> diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index bc5e83fb5819..a921fe92b858 100644 --- a/arch/arm/mach-footbridge/dc21285-timer.c +++ b/arch/arm/mach-footbridge/dc21285-timer.c @@ -4,10 +4,11 @@ * Copyright (C) 1998 Russell King. * Copyright (C) 1998 Phil Blundell */ +#include <linux/clockchips.h> +#include <linux/clocksource.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/spinlock.h> #include <asm/irq.h> @@ -16,32 +17,76 @@ #include "common.h" -/* - * Footbridge timer 1 support. - */ -static unsigned long timer1_latch; +static cycle_t cksrc_dc21285_read(struct clocksource *cs) +{ + return cs->mask - *CSR_TIMER2_VALUE; +} -static unsigned long timer1_gettimeoffset (void) +static int cksrc_dc21285_enable(struct clocksource *cs) { - unsigned long value = timer1_latch - *CSR_TIMER1_VALUE; + *CSR_TIMER2_LOAD = cs->mask; + *CSR_TIMER2_CLR = 0; + *CSR_TIMER2_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16; + return 0; +} - return ((tick_nsec / 1000) * value) / timer1_latch; +static int cksrc_dc21285_disable(struct clocksource *cs) +{ + *CSR_TIMER2_CNTL = 0; } -static irqreturn_t -timer1_interrupt(int irq, void *dev_id) +static struct clocksource cksrc_dc21285 = { + .name = "dc21285_timer2", + .rating = 200, + .read = cksrc_dc21285_read, + .enable = cksrc_dc21285_enable, + .disable = cksrc_dc21285_disable, + .mask = CLOCKSOURCE_MASK(24), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void ckevt_dc21285_set_mode(enum clock_event_mode mode, + struct clock_event_device *c) { + switch (mode) { + case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_PERIODIC: + *CSR_TIMER1_CLR = 0; + *CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ); + *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | + TIMER_CNTL_DIV16; + break; + + default: + *CSR_TIMER1_CNTL = 0; + break; + } +} + +static struct clock_event_device ckevt_dc21285 = { + .name = "dc21285_timer1", + .features = CLOCK_EVT_FEAT_PERIODIC, + .rating = 200, + .irq = IRQ_TIMER1, + .set_mode = ckevt_dc21285_set_mode, +}; + +static irqreturn_t timer1_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *ce = dev_id; + *CSR_TIMER1_CLR = 0; - timer_tick(); + ce->event_handler(ce); return IRQ_HANDLED; } static struct irqaction footbridge_timer_irq = { - .name = "Timer1 timer tick", + .name = "dc21285_timer1", .handler = timer1_interrupt, .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .dev_id = &ckevt_dc21285, }; /* @@ -49,16 +94,19 @@ static struct irqaction footbridge_timer_irq = { */ static void __init footbridge_timer_init(void) { - timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ); + struct clock_event_device *ce = &ckevt_dc21285; + + clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16); + + setup_irq(ce->irq, &footbridge_timer_irq); - *CSR_TIMER1_CLR = 0; - *CSR_TIMER1_LOAD = timer1_latch; - *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; + clockevents_calc_mult_shift(ce, mem_fclk_21285, 5); + ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce); + ce->min_delta_ns = clockevent_delta2ns(0x000004, ce); - setup_irq(IRQ_TIMER1, &footbridge_timer_irq); + clockevents_register_device(ce); } struct sys_timer footbridge_timer = { .init = footbridge_timer_init, - .offset = timer1_gettimeoffset, }; diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S index 3c9e0c40c679..30b971d65815 100644 --- a/arch/arm/mach-footbridge/include/mach/debug-macro.S +++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S @@ -17,8 +17,8 @@ /* For NetWinder debugging */ .macro addruart, rp, rv mov \rp, #0x000003f8 - orr \rv, \rp, #0x7c000000 @ physical - orr \rp, \rp, #0xff000000 @ virtual + orr \rv, \rp, #0xff000000 @ virtual + orr \rp, \rp, #0x7c000000 @ physical .endm #define UART_SHIFT 0 diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h index 51dd902043ad..b6fdf23ecf6c 100644 --- a/arch/arm/mach-footbridge/include/mach/hardware.h +++ b/arch/arm/mach-footbridge/include/mach/hardware.h @@ -23,26 +23,33 @@ * 0xf9000000 0x50000000 1MB Cache flush * 0xf0000000 0x80000000 16MB ISA memory */ + +#ifdef CONFIG_MMU +#define MMU_IO(a, b) (a) +#else +#define MMU_IO(a, b) (b) +#endif + #define XBUS_SIZE 0x00100000 -#define XBUS_BASE 0xff800000 +#define XBUS_BASE MMU_IO(0xff800000, 0x40000000) #define ARMCSR_SIZE 0x00100000 -#define ARMCSR_BASE 0xfe000000 +#define ARMCSR_BASE MMU_IO(0xfe000000, 0x42000000) #define WFLUSH_SIZE 0x00100000 -#define WFLUSH_BASE 0xfd000000 +#define WFLUSH_BASE MMU_IO(0xfd000000, 0x78000000) #define PCIIACK_SIZE 0x00100000 -#define PCIIACK_BASE 0xfc000000 +#define PCIIACK_BASE MMU_IO(0xfc000000, 0x79000000) #define PCICFG1_SIZE 0x01000000 -#define PCICFG1_BASE 0xfb000000 +#define PCICFG1_BASE MMU_IO(0xfb000000, 0x7a000000) #define PCICFG0_SIZE 0x01000000 -#define PCICFG0_BASE 0xfa000000 +#define PCICFG0_BASE MMU_IO(0xfa000000, 0x7b000000) #define PCIMEM_SIZE 0x01000000 -#define PCIMEM_BASE 0xf0000000 +#define PCIMEM_BASE MMU_IO(0xf0000000, 0x80000000) #define XBUS_LEDS ((volatile unsigned char *)(XBUS_BASE + 0x12000)) #define XBUS_LED_AMBER (1 << 0) diff --git a/arch/arm/mach-footbridge/include/mach/io.h b/arch/arm/mach-footbridge/include/mach/io.h index 101a4fe90bde..32e4cc397c28 100644 --- a/arch/arm/mach-footbridge/include/mach/io.h +++ b/arch/arm/mach-footbridge/include/mach/io.h @@ -14,8 +14,14 @@ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H -#define PCIO_SIZE 0x00100000 -#define PCIO_BASE 0xff000000 +#ifdef CONFIG_MMU +#define MMU_IO(a, b) (a) +#else +#define MMU_IO(a, b) (b) +#endif + +#define PCIO_SIZE 0x00100000 +#define PCIO_BASE MMU_IO(0xff000000, 0x7c000000) #define IO_SPACE_LIMIT 0xffff diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c index f488fa2082d7..441c6ce0d555 100644 --- a/arch/arm/mach-footbridge/isa-timer.c +++ b/arch/arm/mach-footbridge/isa-timer.c @@ -4,10 +4,13 @@ * Copyright (C) 1998 Russell King. * Copyright (C) 1998 Phil Blundell */ +#include <linux/clockchips.h> +#include <linux/clocksource.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/timex.h> #include <asm/irq.h> @@ -15,77 +18,115 @@ #include "common.h" -/* - * ISA timer tick support - */ -#define mSEC_10_from_14 ((14318180 + 100) / 200) +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 + +#define PIT_LATCH ((PIT_TICK_RATE + HZ / 2) / HZ) -static unsigned long isa_gettimeoffset(void) +static cycle_t pit_read(struct clocksource *cs) { + unsigned long flags; + static int old_count; + static u32 old_jifs; int count; + u32 jifs; - static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */ - static unsigned long jiffies_p = 0; + raw_local_irq_save(flags); - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; + jifs = jiffies; + outb_p(0x00, PIT_MODE); /* latch the count */ + count = inb_p(PIT_CH0); /* read the latched count */ + count |= inb_p(PIT_CH0) << 8; - /* timer count may underflow right here */ - outb_p(0x00, 0x43); /* latch the count ASAP */ + if (count > old_count && jifs == old_jifs) + count = old_count; - count = inb_p(0x40); /* read the latched count */ + old_count = count; + old_jifs = jifs; - /* - * We do this guaranteed double memory access instead of a _p - * postfix in the previous port access. Wheee, hackady hack - */ - jiffies_t = jiffies; + raw_local_irq_restore(flags); - count |= inb_p(0x40) << 8; + count = (PIT_LATCH - 1) - count; - /* Detect timer underflows. If we haven't had a timer tick since - the last time we were called, and time is apparently going - backwards, the counter must have wrapped during this routine. */ - if ((jiffies_t == jiffies_p) && (count > count_p)) - count -= (mSEC_10_from_14/6); - else - jiffies_p = jiffies_t; + return (cycle_t)(jifs * PIT_LATCH) + count; +} - count_p = count; +static struct clocksource pit_cs = { + .name = "pit", + .rating = 110, + .read = pit_read, + .mask = CLOCKSOURCE_MASK(32), +}; - count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000); - count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6); +static void pit_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + unsigned long flags; + + raw_local_irq_save(flags); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + outb_p(0x34, PIT_MODE); + outb_p(PIT_LATCH & 0xff, PIT_CH0); + outb_p(PIT_LATCH >> 8, PIT_CH0); + break; + + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + outb_p(0x30, PIT_MODE); + outb_p(0, PIT_CH0); + outb_p(0, PIT_CH0); + break; + + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_RESUME: + break; + } + local_irq_restore(flags); +} - return count; +static int pit_set_next_event(unsigned long delta, + struct clock_event_device *evt) +{ + return 0; } -static irqreturn_t -isa_timer_interrupt(int irq, void *dev_id) +static struct clock_event_device pit_ce = { + .name = "pit", + .features = CLOCK_EVT_FEAT_PERIODIC, + .set_mode = pit_set_mode, + .set_next_event = pit_set_next_event, + .shift = 32, +}; + +static irqreturn_t pit_timer_interrupt(int irq, void *dev_id) { - timer_tick(); + struct clock_event_device *ce = dev_id; + ce->event_handler(ce); return IRQ_HANDLED; } -static struct irqaction isa_timer_irq = { - .name = "ISA timer tick", - .handler = isa_timer_interrupt, +static struct irqaction pit_timer_irq = { + .name = "pit", + .handler = pit_timer_interrupt, .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .dev_id = &pit_ce, }; static void __init isa_timer_init(void) { - /* enable PIT timer */ - /* set for periodic (4) and LSB/MSB write (0x30) */ - outb(0x34, 0x43); - outb((mSEC_10_from_14/6) & 0xFF, 0x40); - outb((mSEC_10_from_14/6) >> 8, 0x40); + pit_ce.cpumask = cpumask_of(smp_processor_id()); + pit_ce.mult = div_sc(PIT_TICK_RATE, NSEC_PER_SEC, pit_ce.shift); + pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce); + pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce); + + clocksource_register_hz(&pit_cs, PIT_TICK_RATE); - setup_irq(IRQ_ISA_TIMER, &isa_timer_irq); + setup_irq(pit_ce.irq, &pit_timer_irq); + clockevents_register_device(&pit_ce); } struct sys_timer isa_timer = { .init = isa_timer_init, - .offset = isa_gettimeoffset, }; diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c index 2ba096de0034..0cf7a07c3f3f 100644 --- a/arch/arm/mach-gemini/board-nas4220b.c +++ b/arch/arm/mach-gemini/board-nas4220b.c @@ -98,6 +98,7 @@ static void __init ib4220b_init(void) platform_register_pflash(SZ_16M, NULL, 0); platform_device_register(&ib4220b_led_device); platform_device_register(&ib4220b_key_device); + platform_register_rtc(); } MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B") diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c index a9a0d8b01942..4fa09af99495 100644 --- a/arch/arm/mach-gemini/board-rut1xx.c +++ b/arch/arm/mach-gemini/board-rut1xx.c @@ -82,6 +82,7 @@ static void __init rut1xx_init(void) platform_register_pflash(SZ_8M, NULL, 0); platform_device_register(&rut1xx_leds); platform_device_register(&rut1xx_keys_device); + platform_register_rtc(); } MACHINE_START(RUT100, "Teltonika RUT100") diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c index 8b88d50d4337..af7b68a6b258 100644 --- a/arch/arm/mach-gemini/board-wbd111.c +++ b/arch/arm/mach-gemini/board-wbd111.c @@ -130,6 +130,7 @@ static void __init wbd111_init(void) wbd111_num_partitions); platform_device_register(&wbd111_leds_device); platform_device_register(&wbd111_keys_device); + platform_register_rtc(); } MACHINE_START(WBD111, "Wiliboard WBD-111") diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c index 1eebcecd1c33..99e5bbecf923 100644 --- a/arch/arm/mach-gemini/board-wbd222.c +++ b/arch/arm/mach-gemini/board-wbd222.c @@ -130,6 +130,7 @@ static void __init wbd222_init(void) wbd222_num_partitions); platform_device_register(&wbd222_leds_device); platform_device_register(&wbd222_keys_device); + platform_register_rtc(); } MACHINE_START(WBD222, "Wiliboard WBD-222") diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h index 9392834a214f..7670c39acb2f 100644 --- a/arch/arm/mach-gemini/common.h +++ b/arch/arm/mach-gemini/common.h @@ -18,6 +18,7 @@ extern void gemini_map_io(void); extern void gemini_init_irq(void); extern void gemini_timer_init(void); extern void gemini_gpio_init(void); +extern void platform_register_rtc(void); /* Common platform devices registration functions */ extern int platform_register_uart(void); diff --git a/arch/arm/mach-gemini/devices.c b/arch/arm/mach-gemini/devices.c index 6b525253d027..5cff29818b73 100644 --- a/arch/arm/mach-gemini/devices.c +++ b/arch/arm/mach-gemini/devices.c @@ -90,3 +90,29 @@ int platform_register_pflash(unsigned int size, struct mtd_partition *parts, return platform_device_register(&pflash_device); } + +static struct resource gemini_rtc_resources[] = { + [0] = { + .start = GEMINI_RTC_BASE, + .end = GEMINI_RTC_BASE + 0x24, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_RTC, + .end = IRQ_RTC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device gemini_rtc_device = { + .name = "rtc-gemini", + .id = 0, + .num_resources = ARRAY_SIZE(gemini_rtc_resources), + .resource = gemini_rtc_resources, +}; + +int __init platform_register_rtc(void) +{ + return platform_device_register(&gemini_rtc_device); +} + diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c index aa76cfd9f348..8382e7902078 100644 --- a/arch/arm/mach-imx/mach-mx25_3ds.c +++ b/arch/arm/mach-imx/mach-mx25_3ds.c @@ -180,7 +180,7 @@ static const uint32_t mx25pdk_keymap[] = { KEY(3, 3, KEY_POWER), }; -static const struct matrix_keymap_data mx25pdk_keymap_data __initdata = { +static const struct matrix_keymap_data mx25pdk_keymap_data __initconst = { .keymap = mx25pdk_keymap, .keymap_size = ARRAY_SIZE(mx25pdk_keymap), }; diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 4dc68d6bb6be..9fd894271d5d 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -432,7 +432,7 @@ static struct clocksource clocksource_ixp4xx = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -unsigned long ixp4xx_timer_freq = FREQ; +unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; EXPORT_SYMBOL(ixp4xx_timer_freq); static void __init ixp4xx_clocksource_init(void) { @@ -496,7 +496,7 @@ static struct clock_event_device clockevent_ixp4xx = { static void __init ixp4xx_clockevent_init(void) { - clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC, + clockevent_ixp4xx.mult = div_sc(IXP4XX_TIMER_FREQ, NSEC_PER_SEC, clockevent_ixp4xx.shift); clockevent_ixp4xx.max_delta_ns = clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx); diff --git a/arch/arm/mach-ixp4xx/include/mach/timex.h b/arch/arm/mach-ixp4xx/include/mach/timex.h index 2c3f93c3eb79..c9e930f29339 100644 --- a/arch/arm/mach-ixp4xx/include/mach/timex.h +++ b/arch/arm/mach-ixp4xx/include/mach/timex.h @@ -10,6 +10,7 @@ * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the * timer register ignores the bottom 2 bits of the LATCH value. */ -#define FREQ 66666000 -#define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) +#define IXP4XX_TIMER_FREQ 66666000 +#define CLOCK_TICK_RATE \ + (((IXP4XX_TIMER_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c index bfdbe4b5a3cc..852f7c9f87d0 100644 --- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c +++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c @@ -265,6 +265,11 @@ void qmgr_release_queue(unsigned int queue) qmgr_queue_descs[queue], queue); qmgr_queue_descs[queue][0] = '\x0'; #endif + + while ((addr = qmgr_get_entry(queue))) + printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n", + queue, addr); + __raw_writel(0, &qmgr_regs->sram[queue]); used_sram_bitmap[0] &= ~mask[0]; @@ -275,10 +280,6 @@ void qmgr_release_queue(unsigned int queue) spin_unlock_irq(&qmgr_lock); module_put(THIS_MODULE); - - while ((addr = qmgr_get_entry(queue))) - printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n", - queue, addr); } static int qmgr_init(void) diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c index b1a362ebfded..ca72a05ed9c1 100644 --- a/arch/arm/mach-mxs/clock-mx23.c +++ b/arch/arm/mach-mxs/clock-mx23.c @@ -304,7 +304,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ reg &= ~BM_CLKCTRL_##dr##_DIV; \ reg |= div << BP_CLKCTRL_##dr##_DIV; \ - if (reg | (1 << clk->enable_shift)) { \ + if (reg & (1 << clk->enable_shift)) { \ pr_err("%s: clock is gated\n", __func__); \ return -EINVAL; \ } \ @@ -347,7 +347,7 @@ static int name##_set_parent(struct clk *clk, struct clk *parent) \ { \ if (parent != clk->parent) { \ __raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit, \ - HW_CLKCTRL_CLKSEQ_TOG); \ + CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG); \ clk->parent = parent; \ } \ \ diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 56312c092a9e..fd1c4c54b8e5 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -355,12 +355,12 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \ } else { \ reg &= ~BM_CLKCTRL_##dr##_DIV; \ reg |= div << BP_CLKCTRL_##dr##_DIV; \ - if (reg | (1 << clk->enable_shift)) { \ + if (reg & (1 << clk->enable_shift)) { \ pr_err("%s: clock is gated\n", __func__); \ return -EINVAL; \ } \ } \ - __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU); \ + __raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr); \ \ for (i = 10000; i; i--) \ if (!(__raw_readl(CLKCTRL_BASE_ADDR + \ @@ -483,7 +483,7 @@ static int name##_set_parent(struct clk *clk, struct clk *parent) \ { \ if (parent != clk->parent) { \ __raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit, \ - HW_CLKCTRL_CLKSEQ_TOG); \ + CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG); \ clk->parent = parent; \ } \ \ @@ -609,7 +609,6 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("duart", NULL, uart_clk) _REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk) _REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk) - _REGISTER_CLOCK("fec.0", NULL, fec_clk) _REGISTER_CLOCK("rtc", NULL, rtc_clk) _REGISTER_CLOCK("pll2", NULL, pll2_clk) _REGISTER_CLOCK(NULL, "hclk", hbus_clk) diff --git a/arch/arm/mach-mxs/clock.c b/arch/arm/mach-mxs/clock.c index e7d2269cf70e..a7093c88e6a6 100644 --- a/arch/arm/mach-mxs/clock.c +++ b/arch/arm/mach-mxs/clock.c @@ -57,7 +57,6 @@ static void __clk_disable(struct clk *clk) if (clk->disable) clk->disable(clk); __clk_disable(clk->parent); - __clk_disable(clk->secondary); } } @@ -68,7 +67,6 @@ static int __clk_enable(struct clk *clk) if (clk->usecount++ == 0) { __clk_enable(clk->parent); - __clk_enable(clk->secondary); if (clk->enable) clk->enable(clk); diff --git a/arch/arm/mach-mxs/gpio.c b/arch/arm/mach-mxs/gpio.c index d7ad7a61366d..61991e4dde44 100644 --- a/arch/arm/mach-mxs/gpio.c +++ b/arch/arm/mach-mxs/gpio.c @@ -68,29 +68,29 @@ static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index, } } -static void mxs_gpio_ack_irq(u32 irq) +static void mxs_gpio_ack_irq(struct irq_data *d) { - u32 gpio = irq_to_gpio(irq); + u32 gpio = irq_to_gpio(d->irq); clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f); } -static void mxs_gpio_mask_irq(u32 irq) +static void mxs_gpio_mask_irq(struct irq_data *d) { - u32 gpio = irq_to_gpio(irq); + u32 gpio = irq_to_gpio(d->irq); set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0); } -static void mxs_gpio_unmask_irq(u32 irq) +static void mxs_gpio_unmask_irq(struct irq_data *d) { - u32 gpio = irq_to_gpio(irq); + u32 gpio = irq_to_gpio(d->irq); set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1); } static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset); -static int mxs_gpio_set_irq_type(u32 irq, u32 type) +static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) { - u32 gpio = irq_to_gpio(irq); + u32 gpio = irq_to_gpio(d->irq); u32 pin_mask = 1 << (gpio & 31); struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; void __iomem *pin_addr; @@ -139,6 +139,8 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) struct mxs_gpio_port *port = (struct mxs_gpio_port *)get_irq_data(irq); u32 gpio_irq_no_base = port->virtual_irq_start; + desc->irq_data.chip->irq_ack(&desc->irq_data); + irq_stat = __raw_readl(port->base + PINCTRL_IRQSTAT(port->id)) & __raw_readl(port->base + PINCTRL_IRQEN(port->id)); @@ -158,9 +160,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) * @param enable enable as wake-up if equal to non-zero * @return This function returns 0 on success. */ -static int mxs_gpio_set_wake_irq(u32 irq, u32 enable) +static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable) { - u32 gpio = irq_to_gpio(irq); + u32 gpio = irq_to_gpio(d->irq); u32 gpio_idx = gpio & 0x1f; struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32]; @@ -180,11 +182,11 @@ static int mxs_gpio_set_wake_irq(u32 irq, u32 enable) } static struct irq_chip gpio_irq_chip = { - .ack = mxs_gpio_ack_irq, - .mask = mxs_gpio_mask_irq, - .unmask = mxs_gpio_unmask_irq, - .set_type = mxs_gpio_set_irq_type, - .set_wake = mxs_gpio_set_wake_irq, + .irq_ack = mxs_gpio_ack_irq, + .irq_mask = mxs_gpio_mask_irq, + .irq_unmask = mxs_gpio_unmask_irq, + .irq_set_type = mxs_gpio_set_irq_type, + .irq_set_wake = mxs_gpio_set_wake_irq, }; static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset, diff --git a/arch/arm/mach-mxs/icoll.c b/arch/arm/mach-mxs/icoll.c index 5dd43ba70058..0f4c120fc169 100644 --- a/arch/arm/mach-mxs/icoll.c +++ b/arch/arm/mach-mxs/icoll.c @@ -34,7 +34,7 @@ static void __iomem *icoll_base = MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR); -static void icoll_ack_irq(unsigned int irq) +static void icoll_ack_irq(struct irq_data *d) { /* * The Interrupt Collector is able to prioritize irqs. @@ -45,22 +45,22 @@ static void icoll_ack_irq(unsigned int irq) icoll_base + HW_ICOLL_LEVELACK); } -static void icoll_mask_irq(unsigned int irq) +static void icoll_mask_irq(struct irq_data *d) { __raw_writel(BM_ICOLL_INTERRUPTn_ENABLE, - icoll_base + HW_ICOLL_INTERRUPTn_CLR(irq)); + icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->irq)); } -static void icoll_unmask_irq(unsigned int irq) +static void icoll_unmask_irq(struct irq_data *d) { __raw_writel(BM_ICOLL_INTERRUPTn_ENABLE, - icoll_base + HW_ICOLL_INTERRUPTn_SET(irq)); + icoll_base + HW_ICOLL_INTERRUPTn_SET(d->irq)); } static struct irq_chip mxs_icoll_chip = { - .ack = icoll_ack_irq, - .mask = icoll_mask_irq, - .unmask = icoll_unmask_irq, + .irq_ack = icoll_ack_irq, + .irq_mask = icoll_mask_irq, + .irq_unmask = icoll_unmask_irq, }; void __init icoll_init_irq(void) diff --git a/arch/arm/mach-mxs/include/mach/clock.h b/arch/arm/mach-mxs/include/mach/clock.h index 041e276d8a32..592c9ab5d760 100644 --- a/arch/arm/mach-mxs/include/mach/clock.h +++ b/arch/arm/mach-mxs/include/mach/clock.h @@ -29,8 +29,6 @@ struct clk { int id; /* Source clock this clk depends on */ struct clk *parent; - /* Secondary clock to enable/disable with this clock */ - struct clk *secondary; /* Reference count of clock enable/disable */ __s8 usecount; /* Register bit position for clock's enable/disable control. */ diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 8d2f2daba0c0..e0a028161dde 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -9,6 +9,7 @@ config ARCH_OMAP730 depends on ARCH_OMAP1 bool "OMAP730 Based System" select CPU_ARM926T + select OMAP_MPU_TIMER select ARCH_OMAP_OTG config ARCH_OMAP850 @@ -22,6 +23,7 @@ config ARCH_OMAP15XX default y bool "OMAP15xx Based System" select CPU_ARM925T + select OMAP_MPU_TIMER config ARCH_OMAP16XX depends on ARCH_OMAP1 diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index 6ee19504845f..ba6009f27677 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -3,12 +3,11 @@ # # Common support -obj-y := io.o id.o sram.o irq.o mux.o flash.o serial.o devices.o dma.o +obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o obj-y += clock.o clock_data.o opp_data.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o -obj-$(CONFIG_OMAP_MPU_TIMER) += time.o obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o # Power Management diff --git a/arch/arm/mach-omap1/include/mach/entry-macro.S b/arch/arm/mach-omap1/include/mach/entry-macro.S index c9be6d4d83e2..bfb4fb1d7382 100644 --- a/arch/arm/mach-omap1/include/mach/entry-macro.S +++ b/arch/arm/mach-omap1/include/mach/entry-macro.S @@ -14,19 +14,6 @@ #include <mach/irqs.h> #include <asm/hardware/gic.h> -/* - * We use __glue to avoid errors with multiple definitions of - * .globl omap_irq_flags as it's included from entry-armv.S but not - * from entry-common.S. - */ -#ifdef __glue - .pushsection .data - .globl omap_irq_flags -omap_irq_flags: - .word 0 - .popsection -#endif - .macro disable_fiq .endm diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 47701584df35..731dd33bff51 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -57,6 +57,7 @@ struct omap_irq_bank { unsigned long wake_enable; }; +u32 omap_irq_flags; static unsigned int irq_bank_count; static struct omap_irq_bank *irq_banks; @@ -176,7 +177,6 @@ static struct irq_chip omap_irq_chip = { void __init omap_init_irq(void) { - extern unsigned int omap_irq_flags; int i, j; #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c index c9088d85da04..453809359ba6 100644 --- a/arch/arm/mach-omap1/lcd_dma.c +++ b/arch/arm/mach-omap1/lcd_dma.c @@ -37,7 +37,7 @@ int omap_lcd_dma_running(void) * On OMAP1510, internal LCD controller will start the transfer * when it gets enabled, so assume DMA running if LCD enabled. */ - if (cpu_is_omap1510()) + if (cpu_is_omap15xx()) if (omap_readw(OMAP_LCDC_CONTROL) & OMAP_LCDC_CTRL_LCD_EN) return 1; @@ -95,7 +95,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); void omap_set_lcd_dma_b1_rotation(int rotate) { - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); BUG(); return; @@ -106,7 +106,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); void omap_set_lcd_dma_b1_mirror(int mirror) { - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); BUG(); } @@ -116,7 +116,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); void omap_set_lcd_dma_b1_vxres(unsigned long vxres) { - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { printk(KERN_ERR "DMA virtual resulotion is not supported " "in 1510 mode\n"); BUG(); @@ -127,7 +127,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); void omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) { - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); BUG(); } @@ -177,7 +177,7 @@ static void set_b1_regs(void) bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); /* 1510 DMA requires the bottom address to be 2 more * than the actual last memory access location. */ - if (cpu_is_omap1510() && + if (cpu_is_omap15xx() && lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) bottom += 2; ei = PIXSTEP(0, 0, 1, 0); @@ -241,7 +241,7 @@ static void set_b1_regs(void) return; /* Suppress warning about uninitialized vars */ } - if (cpu_is_omap1510()) { + if (cpu_is_omap15xx()) { omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); @@ -343,7 +343,7 @@ void omap_free_lcd_dma(void) BUG(); return; } - if (!cpu_is_omap1510()) + if (!cpu_is_omap15xx()) omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, OMAP1610_DMA_LCD_CCR); lcd_dma.reserved = 0; @@ -360,7 +360,7 @@ void omap_enable_lcd_dma(void) * connected. Otherwise the OMAP internal controller will * start the transfer when it gets enabled. */ - if (cpu_is_omap1510() || !lcd_dma.ext_ctrl) + if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) return; w = omap_readw(OMAP1610_DMA_LCD_CTRL); @@ -378,14 +378,14 @@ EXPORT_SYMBOL(omap_enable_lcd_dma); void omap_setup_lcd_dma(void) { BUG_ON(lcd_dma.active); - if (!cpu_is_omap1510()) { + if (!cpu_is_omap15xx()) { /* Set some reasonable defaults */ omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); } set_b1_regs(); - if (!cpu_is_omap1510()) { + if (!cpu_is_omap15xx()) { u16 w; w = omap_readw(OMAP1610_DMA_LCD_CCR); @@ -407,7 +407,7 @@ void omap_stop_lcd_dma(void) u16 w; lcd_dma.active = 0; - if (cpu_is_omap1510() || !lcd_dma.ext_ctrl) + if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) return; w = omap_readw(OMAP1610_DMA_LCD_CCR); diff --git a/arch/arm/mach-omap1/pm.h b/arch/arm/mach-omap1/pm.h index 56a647986ae9..cd926dcb5e7f 100644 --- a/arch/arm/mach-omap1/pm.h +++ b/arch/arm/mach-omap1/pm.h @@ -123,9 +123,9 @@ extern void allow_idle_sleep(void); extern void omap1_pm_idle(void); extern void omap1_pm_suspend(void); -extern void omap7xx_cpu_suspend(unsigned short, unsigned short); -extern void omap1510_cpu_suspend(unsigned short, unsigned short); -extern void omap1610_cpu_suspend(unsigned short, unsigned short); +extern void omap7xx_cpu_suspend(unsigned long, unsigned long); +extern void omap1510_cpu_suspend(unsigned long, unsigned long); +extern void omap1610_cpu_suspend(unsigned long, unsigned long); extern void omap7xx_idle_loop_suspend(void); extern void omap1510_idle_loop_suspend(void); extern void omap1610_idle_loop_suspend(void); diff --git a/arch/arm/mach-omap1/sleep.S b/arch/arm/mach-omap1/sleep.S index ef771ce8b030..c875bdc902c5 100644 --- a/arch/arm/mach-omap1/sleep.S +++ b/arch/arm/mach-omap1/sleep.S @@ -58,6 +58,7 @@ */ #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) + .align 3 ENTRY(omap7xx_cpu_suspend) @ save registers on stack @@ -137,6 +138,7 @@ ENTRY(omap7xx_cpu_suspend_sz) #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */ #ifdef CONFIG_ARCH_OMAP15XX + .align 3 ENTRY(omap1510_cpu_suspend) @ save registers on stack @@ -211,6 +213,7 @@ ENTRY(omap1510_cpu_suspend_sz) #endif /* CONFIG_ARCH_OMAP15XX */ #if defined(CONFIG_ARCH_OMAP16XX) + .align 3 ENTRY(omap1610_cpu_suspend) @ save registers on stack diff --git a/arch/arm/mach-omap1/sram.S b/arch/arm/mach-omap1/sram.S index 7724e520d07c..692587d07ea5 100644 --- a/arch/arm/mach-omap1/sram.S +++ b/arch/arm/mach-omap1/sram.S @@ -18,6 +18,7 @@ /* * Reprograms ULPD and CKCTL. */ + .align 3 ENTRY(omap1_sram_reprogram_clock) stmfd sp!, {r0 - r12, lr} @ save registers on stack diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index ed7a61ff916a..6885d2fac183 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c @@ -49,11 +49,15 @@ #include <mach/hardware.h> #include <asm/leds.h> #include <asm/irq.h> +#include <asm/sched_clock.h> + #include <asm/mach/irq.h> #include <asm/mach/time.h> #include <plat/common.h> +#ifdef CONFIG_OMAP_MPU_TIMER + #define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE #define OMAP_MPU_TIMER_OFFSET 0x100 @@ -67,7 +71,7 @@ typedef struct { ((volatile omap_mpu_timer_regs_t*)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE + \ (n)*OMAP_MPU_TIMER_OFFSET)) -static inline unsigned long omap_mpu_timer_read(int nr) +static inline unsigned long notrace omap_mpu_timer_read(int nr) { volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); return timer->read_tim; @@ -212,6 +216,32 @@ static struct clocksource clocksource_mpu = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static DEFINE_CLOCK_DATA(cd); + +static inline unsigned long long notrace _omap_mpu_sched_clock(void) +{ + u32 cyc = mpu_read(&clocksource_mpu); + return cyc_to_sched_clock(&cd, cyc, (u32)~0); +} + +#ifndef CONFIG_OMAP_32K_TIMER +unsigned long long notrace sched_clock(void) +{ + return _omap_mpu_sched_clock(); +} +#else +static unsigned long long notrace omap_mpu_sched_clock(void) +{ + return _omap_mpu_sched_clock(); +} +#endif + +static void notrace mpu_update_sched_clock(void) +{ + u32 cyc = mpu_read(&clocksource_mpu); + update_sched_clock(&cd, cyc, (u32)~0); +} + static void __init omap_init_clocksource(unsigned long rate) { static char err[] __initdata = KERN_ERR @@ -219,17 +249,13 @@ static void __init omap_init_clocksource(unsigned long rate) setup_irq(INT_TIMER2, &omap_mpu_timer2_irq); omap_mpu_timer_start(1, ~0, 1); + init_sched_clock(&cd, mpu_update_sched_clock, 32, rate); if (clocksource_register_hz(&clocksource_mpu, rate)) printk(err, clocksource_mpu.name); } -/* - * --------------------------------------------------------------------------- - * Timer initialization - * --------------------------------------------------------------------------- - */ -static void __init omap_timer_init(void) +static void __init omap_mpu_timer_init(void) { struct clk *ck_ref = clk_get(NULL, "ck_ref"); unsigned long rate; @@ -246,6 +272,66 @@ static void __init omap_timer_init(void) omap_init_clocksource(rate); } +#else +static inline void omap_mpu_timer_init(void) +{ + pr_err("Bogus timer, should not happen\n"); +} +#endif /* CONFIG_OMAP_MPU_TIMER */ + +#if defined(CONFIG_OMAP_MPU_TIMER) && defined(CONFIG_OMAP_32K_TIMER) +static unsigned long long (*preferred_sched_clock)(void); + +unsigned long long notrace sched_clock(void) +{ + if (!preferred_sched_clock) + return 0; + + return preferred_sched_clock(); +} + +static inline void preferred_sched_clock_init(bool use_32k_sched_clock) +{ + if (use_32k_sched_clock) + preferred_sched_clock = omap_32k_sched_clock; + else + preferred_sched_clock = omap_mpu_sched_clock; +} +#else +static inline void preferred_sched_clock_init(bool use_32k_sched_clcok) +{ +} +#endif + +static inline int omap_32k_timer_usable(void) +{ + int res = false; + + if (cpu_is_omap730() || cpu_is_omap15xx()) + return res; + +#ifdef CONFIG_OMAP_32K_TIMER + res = omap_32k_timer_init(); +#endif + + return res; +} + +/* + * --------------------------------------------------------------------------- + * Timer initialization + * --------------------------------------------------------------------------- + */ +static void __init omap_timer_init(void) +{ + if (omap_32k_timer_usable()) { + preferred_sched_clock_init(1); + } else { + omap_mpu_timer_init(); + preferred_sched_clock_init(0); + } +} + struct sys_timer omap_timer = { .init = omap_timer_init, }; diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index 20cfbcc6c60c..13d7b8f145bd 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -52,10 +52,9 @@ #include <asm/irq.h> #include <asm/mach/irq.h> #include <asm/mach/time.h> +#include <plat/common.h> #include <plat/dmtimer.h> -struct sys_timer omap_timer; - /* * --------------------------------------------------------------------------- * 32KHz OS timer @@ -181,14 +180,14 @@ static __init void omap_init_32k_timer(void) * Timer initialization * --------------------------------------------------------------------------- */ -static void __init omap_timer_init(void) +bool __init omap_32k_timer_init(void) { + omap_init_clocksource_32k(); + #ifdef CONFIG_OMAP_DM_TIMER omap_dm_timer_init(); #endif omap_init_32k_timer(); -} -struct sys_timer omap_timer = { - .init = omap_timer_init, -}; + return true; +} diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1a2cf6226a55..b69fa0a0299e 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -45,6 +45,7 @@ config ARCH_OMAP4 select CPU_V7 select ARM_GIC select PL310_ERRATA_588369 + select PL310_ERRATA_727915 select ARM_ERRATA_720789 select ARCH_HAS_OPP select PM_OPP if PM diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c index 5b0c77732dfc..8f9a64d650ee 100644 --- a/arch/arm/mach-omap2/board-cm-t3517.c +++ b/arch/arm/mach-omap2/board-cm-t3517.c @@ -124,8 +124,9 @@ static inline void cm_t3517_init_hecc(void) {} #if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE) #define RTC_IO_GPIO (153) #define RTC_WR_GPIO (154) -#define RTC_RD_GPIO (160) +#define RTC_RD_GPIO (53) #define RTC_CS_GPIO (163) +#define RTC_CS_EN_GPIO (160) struct v3020_platform_data cm_t3517_v3020_pdata = { .use_gpio = 1, @@ -145,6 +146,16 @@ static struct platform_device cm_t3517_rtc_device = { static void __init cm_t3517_init_rtc(void) { + int err; + + err = gpio_request(RTC_CS_EN_GPIO, "rtc cs en"); + if (err) { + pr_err("CM-T3517: rtc cs en gpio request failed: %d\n", err); + return; + } + + gpio_direction_output(RTC_CS_EN_GPIO, 1); + platform_device_register(&cm_t3517_rtc_device); } #else @@ -214,12 +225,12 @@ static struct mtd_partition cm_t3517_nand_partitions[] = { }, { .name = "linux", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */ + .offset = MTDPART_OFS_APPEND, /* Offset = 0x2A0000 */ .size = 32 * NAND_BLOCK_SIZE, }, { .name = "rootfs", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */ + .offset = MTDPART_OFS_APPEND, /* Offset = 0x6A0000 */ .size = MTDPART_SIZ_FULL, }, }; @@ -256,11 +267,19 @@ static void __init cm_t3517_init_irq(void) static struct omap_board_mux board_mux[] __initdata = { /* GPIO186 - Green LED */ OMAP3_MUX(SYS_CLKOUT2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT), - /* RTC GPIOs: IO, WR#, RD#, CS# */ + + /* RTC GPIOs: */ + /* IO - GPIO153 */ OMAP3_MUX(MCBSP4_DR, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), + /* WR# - GPIO154 */ OMAP3_MUX(MCBSP4_DX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), - OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), + /* RD# - GPIO53 */ + OMAP3_MUX(GPMC_NCS2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), + /* CS# - GPIO163 */ OMAP3_MUX(UART3_CTS_RCTX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), + /* CS EN - GPIO160 */ + OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), + /* HSUSB1 RESET */ OMAP3_MUX(UART2_TX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT), /* HSUSB2 RESET */ diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 00bb1fc5e017..9a2a31e011ce 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -115,9 +115,6 @@ static struct omap2_hsmmc_info mmc[] = { static int devkit8000_panel_enable_lcd(struct omap_dss_device *dssdev) { - twl_i2c_write_u8(TWL4030_MODULE_GPIO, 0x80, REG_GPIODATADIR1); - twl_i2c_write_u8(TWL4030_MODULE_LED, 0x0, 0x0); - if (gpio_is_valid(dssdev->reset_gpio)) gpio_set_value_cansleep(dssdev->reset_gpio, 1); return 0; @@ -247,6 +244,8 @@ static struct gpio_led gpio_leds[]; static int devkit8000_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { + int ret; + omap_mux_init_gpio(29, OMAP_PIN_INPUT); /* gpio + 0 is "mmc0_cd" (input/IRQ) */ mmc[0].gpio_cd = gpio + 0; @@ -255,17 +254,23 @@ static int devkit8000_twl_gpio_setup(struct device *dev, /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; - /* gpio + 1 is "LCD_PWREN" (out, active high) */ - devkit8000_lcd_device.reset_gpio = gpio + 1; - gpio_request(devkit8000_lcd_device.reset_gpio, "LCD_PWREN"); - /* Disable until needed */ - gpio_direction_output(devkit8000_lcd_device.reset_gpio, 0); + /* TWL4030_GPIO_MAX + 0 is "LCD_PWREN" (out, active high) */ + devkit8000_lcd_device.reset_gpio = gpio + TWL4030_GPIO_MAX + 0; + ret = gpio_request_one(devkit8000_lcd_device.reset_gpio, + GPIOF_DIR_OUT | GPIOF_INIT_LOW, "LCD_PWREN"); + if (ret < 0) { + devkit8000_lcd_device.reset_gpio = -EINVAL; + printk(KERN_ERR "Failed to request GPIO for LCD_PWRN\n"); + } /* gpio + 7 is "DVI_PD" (out, active low) */ devkit8000_dvi_device.reset_gpio = gpio + 7; - gpio_request(devkit8000_dvi_device.reset_gpio, "DVI PowerDown"); - /* Disable until needed */ - gpio_direction_output(devkit8000_dvi_device.reset_gpio, 0); + ret = gpio_request_one(devkit8000_dvi_device.reset_gpio, + GPIOF_DIR_OUT | GPIOF_INIT_LOW, "DVI PowerDown"); + if (ret < 0) { + devkit8000_dvi_device.reset_gpio = -EINVAL; + printk(KERN_ERR "Failed to request GPIO for DVI PowerDown\n"); + } return 0; } @@ -275,8 +280,7 @@ static struct twl4030_gpio_platform_data devkit8000_gpio_data = { .irq_base = TWL4030_GPIO_IRQ_BASE, .irq_end = TWL4030_GPIO_IRQ_END, .use_leds = true, - .pullups = BIT(1), - .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13) + .pulldowns = BIT(1) | BIT(2) | BIT(6) | BIT(8) | BIT(13) | BIT(15) | BIT(16) | BIT(17), .setup = devkit8000_twl_gpio_setup, }; diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index e001a048dc0c..e944025d5ef8 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -409,8 +409,6 @@ static void __init omap4_panda_init(void) platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); omap_serial_init(); omap4_twl6030_hsmmc_init(mmc); - /* OMAP4 Panda uses internal transceiver so register nop transceiver */ - usb_nop_xceiv_register(); omap4_ehci_init(); usb_musb_init(&musb_board_data); } diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c index cb77be7ac44f..39a71bb8a308 100644 --- a/arch/arm/mach-omap2/board-rm680.c +++ b/arch/arm/mach-omap2/board-rm680.c @@ -40,9 +40,6 @@ static struct regulator_consumer_supply rm680_vemmc_consumers[] = { static struct regulator_init_data rm680_vemmc = { .constraints = { .name = "rm680_vemmc", - .min_uV = 2900000, - .max_uV = 2900000, - .apply_uV = 1, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_STATUS diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c index 337392c3f549..acb7ae5b0a25 100644 --- a/arch/arm/mach-omap2/clkt_dpll.c +++ b/arch/arm/mach-omap2/clkt_dpll.c @@ -77,7 +77,7 @@ static int _dpll_test_fint(struct clk *clk, u8 n) dd = clk->dpll_data; /* DPLL divider must result in a valid jitter correction val */ - fint = clk->parent->rate / (n + 1); + fint = clk->parent->rate / n; if (fint < DPLL_FINT_BAND1_MIN) { pr_debug("rejecting n=%d due to Fint failure, " diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index e8cb32fd7f13..de9ec8ddd2ae 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -34,7 +34,6 @@ #include "cm2_44xx.h" #include "cm-regbits-44xx.h" #include "prm44xx.h" -#include "prm44xx.h" #include "prm-regbits-44xx.h" #include "control.h" #include "scrm44xx.h" diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index e20b98636ab4..58e42f76603f 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -423,6 +423,12 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; + if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { + pr_err("clockdomain: %s/%s: %s: not yet implemented\n", + clkdm1->name, clkdm2->name, __func__); + return -EINVAL; + } + if (!clkdm1 || !clkdm2) return -EINVAL; @@ -458,6 +464,12 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) { struct clkdm_dep *cd; + if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { + pr_err("clockdomain: %s/%s: %s: not yet implemented\n", + clkdm1->name, clkdm2->name, __func__); + return -EINVAL; + } + if (!clkdm1 || !clkdm2) return -EINVAL; @@ -500,6 +512,12 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2) if (!clkdm1 || !clkdm2) return -EINVAL; + if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { + pr_err("clockdomain: %s/%s: %s: not yet implemented\n", + clkdm1->name, clkdm2->name, __func__); + return -EINVAL; + } + cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs); if (IS_ERR(cd)) { pr_debug("clockdomain: hardware cannot set/clear wake up of " @@ -527,6 +545,12 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm) struct clkdm_dep *cd; u32 mask = 0; + if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) { + pr_err("clockdomain: %s: %s: not yet implemented\n", + clkdm->name, __func__); + return -EINVAL; + } + if (!clkdm) return -EINVAL; @@ -830,8 +854,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm) * dependency code and data for OMAP4. */ if (cpu_is_omap44xx()) { - WARN_ONCE(1, "clockdomain: OMAP4 wakeup/sleep dependency " - "support is not yet implemented\n"); + pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name); } else { if (atomic_read(&clkdm->usecount) > 0) _clkdm_add_autodeps(clkdm); @@ -872,8 +895,7 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm) * dependency code and data for OMAP4. */ if (cpu_is_omap44xx()) { - WARN_ONCE(1, "clockdomain: OMAP4 wakeup/sleep dependency " - "support is not yet implemented\n"); + pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name); } else { if (atomic_read(&clkdm->usecount) > 0) _clkdm_del_autodeps(clkdm); diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index 51920fc7fc52..10622c914abc 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -30,8 +30,6 @@ #include "cm1_44xx.h" #include "cm2_44xx.h" -#include "cm1_44xx.h" -#include "cm2_44xx.h" #include "cm-regbits-44xx.h" #include "prm44xx.h" #include "prcm44xx.h" diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index d2f15f5cfd36..34922b2d2e3f 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -264,7 +264,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) if (IS_ERR(od)) { pr_err("%s: Cant build omap_device for %s:%s.\n", __func__, name, oh->name); - return IS_ERR(od); + return PTR_ERR(od); } mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0); diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S index befa321c4c13..81985a665cb3 100644 --- a/arch/arm/mach-omap2/include/mach/entry-macro.S +++ b/arch/arm/mach-omap2/include/mach/entry-macro.S @@ -38,20 +38,6 @@ */ #ifdef MULTI_OMAP2 - -/* - * We use __glue to avoid errors with multiple definitions of - * .globl omap_irq_base as it's included from entry-armv.S but not - * from entry-common.S. - */ -#ifdef __glue - .pushsection .data - .globl omap_irq_base -omap_irq_base: - .word 0 - .popsection -#endif - /* * Configure the interrupt base on the first interrupt. * See also omap_irq_base_init for setting omap_irq_base. diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index e66687b0b9de..c2032041d26f 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -314,14 +314,13 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data) return omap_hwmod_set_postsetup_state(oh, *(u8 *)data); } +void __iomem *omap_irq_base; + /* * Initialize asm_irq_base for entry-macro.S */ static inline void omap_irq_base_init(void) { - extern void __iomem *omap_irq_base; - -#ifdef MULTI_OMAP2 if (cpu_is_omap24xx()) omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE); else if (cpu_is_omap34xx()) @@ -330,7 +329,6 @@ static inline void omap_irq_base_init(void) omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE); else pr_err("Could not initialize omap_irq_base\n"); -#endif } void __init omap2_init_common_infrastructure(void) diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c index 394413dc7deb..24b88504df0f 100644 --- a/arch/arm/mach-omap2/mailbox.c +++ b/arch/arm/mach-omap2/mailbox.c @@ -193,10 +193,12 @@ static void omap2_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq) { struct omap_mbox2_priv *p = mbox->priv; - u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; - l = mbox_read_reg(p->irqdisable); - l &= ~bit; - mbox_write_reg(l, p->irqdisable); + u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit; + + if (!cpu_is_omap44xx()) + bit = mbox_read_reg(p->irqdisable) & ~bit; + + mbox_write_reg(bit, p->irqdisable); } static void omap2_mbox_ack_irq(struct omap_mbox *mbox, @@ -334,7 +336,7 @@ static struct omap_mbox mbox_iva_info = { .priv = &omap2_mbox_iva_priv, }; -struct omap_mbox *omap2_mboxes[] = { &mbox_iva_info, &mbox_dsp_info, NULL }; +struct omap_mbox *omap2_mboxes[] = { &mbox_dsp_info, &mbox_iva_info, NULL }; #endif #if defined(CONFIG_ARCH_OMAP4) diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index df8d2f2872c6..6c84659cf846 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -160,7 +160,7 @@ static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition, struct omap_mux *mux = NULL; struct omap_mux_entry *e; const char *mode_name; - int found = 0, found_mode, mode0_len = 0; + int found = 0, found_mode = 0, mode0_len = 0; struct list_head *muxmodes = &partition->muxmodes; mode_name = strchr(muxname, '.'); @@ -605,7 +605,7 @@ static void __init omap_mux_dbg_create_entry( list_for_each_entry(e, &partition->muxmodes, node) { struct omap_mux *m = &e->mux; - (void)debugfs_create_file(m->muxnames[0], S_IWUGO, mux_dbg_dir, + (void)debugfs_create_file(m->muxnames[0], S_IWUSR, mux_dbg_dir, m, &omap_mux_dbg_signal_fops); } } @@ -1000,6 +1000,7 @@ int __init omap_mux_init(const char *name, u32 flags, if (!partition->base) { pr_err("%s: Could not ioremap mux partition at 0x%08x\n", __func__, partition->phys); + kfree(partition); return -ENODEV; } diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 19268647ce36..9ef8c29dd817 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -52,6 +52,12 @@ static void omap4_l2x0_disable(void) omap_smc1(0x102, 0x0); } +static void omap4_l2x0_set_debug(unsigned long val) +{ + /* Program PL310 L2 Cache controller debug register */ + omap_smc1(0x100, val); +} + static int __init omap_l2_cache_init(void) { u32 aux_ctrl = 0; @@ -99,6 +105,7 @@ static int __init omap_l2_cache_init(void) * specific one */ outer_cache.disable = omap4_l2x0_disable; + outer_cache.set_debug = omap4_l2x0_set_debug; return 0; } diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 125f56591fb5..a5a83b358ddd 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -637,14 +637,14 @@ static int __init pm_dbg_init(void) } - (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUGO, d, + (void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d, &enable_off_mode, &pm_dbg_option_fops); - (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUGO, d, + (void) debugfs_create_file("sleep_while_idle", S_IRUGO | S_IWUSR, d, &sleep_while_idle, &pm_dbg_option_fops); - (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d, + (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUSR, d, &wakeup_timer_seconds, &pm_dbg_option_fops); (void) debugfs_create_file("wakeup_timer_milliseconds", - S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds, + S_IRUGO | S_IWUSR, d, &wakeup_timer_milliseconds, &pm_dbg_option_fops); pm_dbg_init_done = 1; diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 1c1b0ab5b978..39580e6060e8 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void); extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl, void __iomem *sdrc_power); extern void omap34xx_cpu_suspend(u32 *addr, int save_state); -extern void save_secure_ram_context(u32 *addr); +extern int save_secure_ram_context(u32 *addr); extern void omap3_save_scratchpad_contents(void); extern unsigned int omap24xx_idle_loop_suspend_sz; diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 9e5dc8ed51e9..97feb3ab6a69 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -134,7 +134,7 @@ static void omap2_enter_full_retention(void) /* Block console output in case it is on one of the OMAP UARTs */ if (!is_suspending()) - if (try_acquire_console_sem()) + if (!console_trylock()) goto no_sleep; omap_uart_prepare_idle(0); @@ -151,7 +151,7 @@ static void omap2_enter_full_retention(void) omap_uart_resume_idle(0); if (!is_suspending()) - release_console_sem(); + console_unlock(); no_sleep: if (omap2_pm_debug) { diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 8cbbeade4b8a..2f864e4b085d 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -168,9 +168,10 @@ static void omap3_core_restore_context(void) * once during boot sequence, but this works as we are not using secure * services. */ -static void omap3_save_secure_ram_context(u32 target_mpu_state) +static void omap3_save_secure_ram_context(void) { u32 ret; + int mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); if (omap_type() != OMAP2_DEVICE_TYPE_GP) { /* @@ -181,7 +182,7 @@ static void omap3_save_secure_ram_context(u32 target_mpu_state) pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); ret = _omap_save_secure_sram((u32 *) __pa(omap3_secure_ram_storage)); - pwrdm_set_next_pwrst(mpu_pwrdm, target_mpu_state); + pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state); /* Following is for error tracking, it should not happen */ if (ret) { printk(KERN_ERR "save_secure_sram() returns %08x\n", @@ -398,7 +399,7 @@ void omap_sram_idle(void) if (!is_suspending()) if (per_next_state < PWRDM_POWER_ON || core_next_state < PWRDM_POWER_ON) - if (try_acquire_console_sem()) + if (!console_trylock()) goto console_still_active; /* PER */ @@ -481,7 +482,7 @@ void omap_sram_idle(void) } if (!is_suspending()) - release_console_sem(); + console_unlock(); console_still_active: /* Disable IO-PAD and IO-CHAIN wakeup */ @@ -1094,7 +1095,7 @@ static int __init omap3_pm_init(void) local_fiq_disable(); omap_dma_global_context_save(); - omap3_save_secure_ram_context(PWRDM_POWER_ON); + omap3_save_secure_ram_context(); omap_dma_global_context_restore(); local_irq_enable(); diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c index d5233890370c..cf600e22bf8e 100644 --- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c @@ -19,7 +19,6 @@ #include <plat/prcm.h> #include "powerdomain.h" -#include "prm-regbits-34xx.h" #include "prm.h" #include "prm-regbits-24xx.h" #include "prm-regbits-34xx.h" diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h index 729a644ce852..3300ff6e3cfe 100644 --- a/arch/arm/mach-omap2/prcm_mpu44xx.h +++ b/arch/arm/mach-omap2/prcm_mpu44xx.h @@ -38,8 +38,8 @@ #define OMAP4430_PRCM_MPU_CPU1_INST 0x0800 /* PRCM_MPU clockdomain register offsets (from instance start) */ -#define OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS 0x0000 -#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS 0x0000 +#define OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS 0x0018 +#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS 0x0018 /* diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 302da7403a10..32e91a9c8b6b 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -812,7 +812,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) oh->dev_attr = uart; - acquire_console_sem(); /* in case the earlycon is on the UART */ + console_lock(); /* in case the earlycon is on the UART */ /* * Because of early UART probing, UART did not get idled @@ -838,7 +838,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata) omap_uart_block_sleep(uart); uart->timeout = DEFAULT_TIMEOUT; - release_console_sem(); + console_unlock(); if ((cpu_is_omap34xx() && uart->padconf) || (uart->wk_en && uart->wk_mask)) { diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index c7780cc8d919..b5071a47ec39 100644 --- a/arch/arm/mach-omap2/sleep24xx.S +++ b/arch/arm/mach-omap2/sleep24xx.S @@ -47,6 +47,7 @@ * Note: This code get's copied to internal SRAM at boot. When the OMAP * wakes up it continues execution at the point it went to sleep. */ + .align 3 ENTRY(omap24xx_idle_loop_suspend) stmfd sp!, {r0, lr} @ save registers on stack mov r0, #0 @ clear for mcr setup @@ -82,6 +83,7 @@ ENTRY(omap24xx_idle_loop_suspend_sz) * The DLL load value is not kept in RETENTION or OFF. It needs to be restored * at wake */ + .align 3 ENTRY(omap24xx_cpu_suspend) stmfd sp!, {r0 - r12, lr} @ save registers on stack mov r3, #0x0 @ clear for mcr call diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index 98d8232808b8..951a0be66cf7 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -118,6 +118,7 @@ ENTRY(enable_omap3630_toggle_l2_on_restore) .text /* Function to call rom code to save secure ram context */ + .align 3 ENTRY(save_secure_ram_context) stmfd sp!, {r1-r12, lr} @ save registers on stack adr r3, api_params @ r3 points to parameters @@ -169,6 +170,7 @@ ENTRY(save_secure_ram_context_sz) * depending on the low power mode (non-OFF vs OFF modes), * cf. 'Resume path for xxx mode' comments. */ + .align 3 ENTRY(omap34xx_cpu_suspend) stmfd sp!, {r0-r12, lr} @ save registers on stack diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c index 77ecebf3fae2..1a777e34d0c2 100644 --- a/arch/arm/mach-omap2/smartreflex.c +++ b/arch/arm/mach-omap2/smartreflex.c @@ -282,6 +282,7 @@ error: dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" "interrupt handler. Smartreflex will" "not function as desired\n", __func__); + kfree(name); kfree(sr_info); return ret; } @@ -780,8 +781,7 @@ static int omap_sr_autocomp_show(void *data, u64 *val) struct omap_sr *sr_info = (struct omap_sr *) data; if (!sr_info) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, sr_info->voltdm->name); + pr_warning("%s: omap_sr struct not found\n", __func__); return -EINVAL; } @@ -795,8 +795,7 @@ static int omap_sr_autocomp_store(void *data, u64 val) struct omap_sr *sr_info = (struct omap_sr *) data; if (!sr_info) { - pr_warning("%s: omap_sr struct for sr_%s not found\n", - __func__, sr_info->voltdm->name); + pr_warning("%s: omap_sr struct not found\n", __func__); return -EINVAL; } @@ -834,7 +833,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) if (!pdata) { dev_err(&pdev->dev, "%s: platform data missing\n", __func__); - return -EINVAL; + ret = -EINVAL; + goto err_free_devinfo; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -880,7 +880,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) ret = sr_late_init(sr_info); if (ret) { pr_warning("%s: Error in SR late init\n", __func__); - return ret; + goto err_release_region; } } @@ -891,17 +891,20 @@ static int __init omap_sr_probe(struct platform_device *pdev) * not try to create rest of the debugfs entries. */ vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm); - if (!vdd_dbg_dir) - return -EINVAL; + if (!vdd_dbg_dir) { + ret = -EINVAL; + goto err_release_region; + } dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir); if (IS_ERR(dbg_dir)) { dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n", __func__); - return PTR_ERR(dbg_dir); + ret = PTR_ERR(dbg_dir); + goto err_release_region; } - (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUGO, dbg_dir, + (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, dbg_dir, (void *)sr_info, &pm_sr_fops); (void) debugfs_create_x32("errweight", S_IRUGO, dbg_dir, &sr_info->err_weight); @@ -914,7 +917,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) if (IS_ERR(nvalue_dir)) { dev_err(&pdev->dev, "%s: Unable to create debugfs directory" "for n-values\n", __func__); - return PTR_ERR(nvalue_dir); + ret = PTR_ERR(nvalue_dir); + goto err_release_region; } omap_voltage_get_volttable(sr_info->voltdm, &volt_data); @@ -923,24 +927,16 @@ static int __init omap_sr_probe(struct platform_device *pdev) " corresponding vdd vdd_%s. Cannot create debugfs" "entries for n-values\n", __func__, sr_info->voltdm->name); - return -ENODATA; + ret = -ENODATA; + goto err_release_region; } for (i = 0; i < sr_info->nvalue_count; i++) { - char *name; - char volt_name[32]; - - name = kzalloc(NVALUE_NAME_LEN + 1, GFP_KERNEL); - if (!name) { - dev_err(&pdev->dev, "%s: Unable to allocate memory" - " for n-value directory name\n", __func__); - return -ENOMEM; - } + char name[NVALUE_NAME_LEN + 1]; - strcpy(name, "volt_"); - sprintf(volt_name, "%d", volt_data[i].volt_nominal); - strcat(name, volt_name); - (void) debugfs_create_x32(name, S_IRUGO | S_IWUGO, nvalue_dir, + snprintf(name, sizeof(name), "volt_%d", + volt_data[i].volt_nominal); + (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir, &(sr_info->nvalue_table[i].nvalue)); } @@ -966,7 +962,7 @@ static int __devexit omap_sr_remove(struct platform_device *pdev) } sr_info = _sr_lookup(pdata->voltdm); - if (!sr_info) { + if (IS_ERR(sr_info)) { dev_warn(&pdev->dev, "%s: omap_sr struct not found\n", __func__); return -EINVAL; diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S index 055310cc77de..ff9b9dbcb30e 100644 --- a/arch/arm/mach-omap2/sram242x.S +++ b/arch/arm/mach-omap2/sram242x.S @@ -39,6 +39,7 @@ .text + .align 3 ENTRY(omap242x_sram_ddr_init) stmfd sp!, {r0 - r12, lr} @ save registers on stack @@ -143,6 +144,7 @@ ENTRY(omap242x_sram_ddr_init_sz) * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR] * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0 */ + .align 3 ENTRY(omap242x_sram_reprogram_sdrc) stmfd sp!, {r0 - r10, lr} @ save registers on stack mov r3, #0x0 @ clear for mrc call @@ -238,6 +240,7 @@ ENTRY(omap242x_sram_reprogram_sdrc_sz) /* * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode. */ + .align 3 ENTRY(omap242x_sram_set_prcm) stmfd sp!, {r0-r12, lr} @ regs to stack adr r4, pbegin @ addr of preload start diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S index f9007580aea3..76730209fa0e 100644 --- a/arch/arm/mach-omap2/sram243x.S +++ b/arch/arm/mach-omap2/sram243x.S @@ -39,6 +39,7 @@ .text + .align 3 ENTRY(omap243x_sram_ddr_init) stmfd sp!, {r0 - r12, lr} @ save registers on stack @@ -143,6 +144,7 @@ ENTRY(omap243x_sram_ddr_init_sz) * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR] * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0 */ + .align 3 ENTRY(omap243x_sram_reprogram_sdrc) stmfd sp!, {r0 - r10, lr} @ save registers on stack mov r3, #0x0 @ clear for mrc call @@ -238,6 +240,7 @@ ENTRY(omap243x_sram_reprogram_sdrc_sz) /* * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode. */ + .align 3 ENTRY(omap243x_sram_set_prcm) stmfd sp!, {r0-r12, lr} @ regs to stack adr r4, pbegin @ addr of preload start diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 7f893a29d500..25011ca2145d 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -111,6 +111,7 @@ * since it will cause the ARM MMU to attempt to walk the page tables. * These crashes may be intermittent. */ + .align 3 ENTRY(omap3_sram_configure_core_dpll) stmfd sp!, {r1-r12, lr} @ store regs to stack diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 4e48e786bec7..0fc550e7e482 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -39,9 +39,12 @@ #include <asm/mach/time.h> #include <plat/dmtimer.h> #include <asm/localtimer.h> +#include <asm/sched_clock.h> #include "timer-gp.h" +#include <plat/common.h> + /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */ #define MAX_GPTIMER_ID 12 @@ -176,14 +179,19 @@ static void __init omap2_gp_clockevent_init(void) /* * When 32k-timer is enabled, don't use GPTimer for clocksource * instead, just leave default clocksource which uses the 32k - * sync counter. See clocksource setup in see plat-omap/common.c. + * sync counter. See clocksource setup in plat-omap/counter_32k.c */ -static inline void __init omap2_gp_clocksource_init(void) {} +static void __init omap2_gp_clocksource_init(void) +{ + omap_init_clocksource_32k(); +} + #else /* * clocksource */ +static DEFINE_CLOCK_DATA(cd); static struct omap_dm_timer *gpt_clocksource; static cycle_t clocksource_read_cycles(struct clocksource *cs) { @@ -198,6 +206,15 @@ static struct clocksource clocksource_gpt = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +static void notrace dmtimer_update_sched_clock(void) +{ + u32 cyc; + + cyc = omap_dm_timer_read_counter(gpt_clocksource); + + update_sched_clock(&cd, cyc, (u32)~0); +} + /* Setup free-running counter for clocksource */ static void __init omap2_gp_clocksource_init(void) { @@ -218,6 +235,8 @@ static void __init omap2_gp_clocksource_init(void) omap_dm_timer_set_load_start(gpt, 1, 0); + init_sched_clock(&cd, dmtimer_update_sched_clock, 32, tick_rate); + if (clocksource_register_hz(&clocksource_gpt, tick_rate)) printk(err2, clocksource_gpt.name); } diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index ed6079c94c57..12be525b8df4 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -471,6 +471,7 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd) strcat(name, vdd->voltdm.name); vdd->debug_dir = debugfs_create_dir(name, voltage_dir); + kfree(name); if (IS_ERR(vdd->debug_dir)) { pr_warning("%s: Unable to create debugfs directory for" " vdd_%s\n", __func__, vdd->voltdm.name); diff --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c index 6b2c800a1133..28f667e52ef9 100644 --- a/arch/arm/mach-pxa/colibri-evalboard.c +++ b/arch/arm/mach-pxa/colibri-evalboard.c @@ -50,7 +50,7 @@ static void __init colibri_mmc_init(void) GPIO0_COLIBRI_PXA270_SD_DETECT; if (machine_is_colibri300()) /* PXA300 Colibri */ colibri_mci_platform_data.gpio_card_detect = - GPIO39_COLIBRI_PXA300_SD_DETECT; + GPIO13_COLIBRI_PXA300_SD_DETECT; else /* PXA320 Colibri */ colibri_mci_platform_data.gpio_card_detect = GPIO28_COLIBRI_PXA320_SD_DETECT; diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c index fddb16d07eb0..66dd81cbc8a0 100644 --- a/arch/arm/mach-pxa/colibri-pxa300.c +++ b/arch/arm/mach-pxa/colibri-pxa300.c @@ -41,7 +41,7 @@ static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = { GPIO4_MMC1_DAT1, GPIO5_MMC1_DAT2, GPIO6_MMC1_DAT3, - GPIO39_GPIO, /* SD detect */ + GPIO13_GPIO, /* GPIO13_COLIBRI_PXA300_SD_DETECT */ /* UHC */ GPIO0_2_USBH_PEN, diff --git a/arch/arm/mach-pxa/include/mach/colibri.h b/arch/arm/mach-pxa/include/mach/colibri.h index 388a96f1ef93..cb4236e98a0f 100644 --- a/arch/arm/mach-pxa/include/mach/colibri.h +++ b/arch/arm/mach-pxa/include/mach/colibri.h @@ -60,7 +60,7 @@ static inline void colibri_pxa3xx_init_nand(void) {} #define GPIO113_COLIBRI_PXA270_TS_IRQ 113 /* GPIO definitions for Colibri PXA300/310 */ -#define GPIO39_COLIBRI_PXA300_SD_DETECT 39 +#define GPIO13_COLIBRI_PXA300_SD_DETECT 13 /* GPIO definitions for Colibri PXA320 */ #define GPIO28_COLIBRI_PXA320_SD_DETECT 28 diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h index fd8360c6839d..f15afe012995 100644 --- a/arch/arm/mach-pxa/include/mach/pm.h +++ b/arch/arm/mach-pxa/include/mach/pm.h @@ -22,9 +22,8 @@ struct pxa_cpu_pm_fns { extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns; /* sleep.S */ -extern void pxa25x_cpu_suspend(unsigned int); -extern void pxa27x_cpu_suspend(unsigned int); -extern void pxa_cpu_resume(void); +extern void pxa25x_cpu_suspend(unsigned int, long); +extern void pxa27x_cpu_suspend(unsigned int, long); extern int pxa_pm_enter(suspend_state_t state); extern int pxa_pm_prepare(void); diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c index 405b92a29793..35572c427fa8 100644 --- a/arch/arm/mach-pxa/palm27x.c +++ b/arch/arm/mach-pxa/palm27x.c @@ -323,7 +323,7 @@ static struct platform_pwm_backlight_data palm27x_backlight_data = { .pwm_id = 0, .max_brightness = 0xfe, .dft_brightness = 0x7e, - .pwm_period_ns = 3500, + .pwm_period_ns = 3500 * 1024, .init = palm27x_backlight_init, .notify = palm27x_backlight_notify, .exit = palm27x_backlight_exit, diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 7bf4017326e3..3010193b081e 100644 --- a/arch/arm/mach-pxa/palmz72.c +++ b/arch/arm/mach-pxa/palmz72.c @@ -212,7 +212,7 @@ static unsigned long store_ptr; static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg) { /* setup the resume_info struct for the original bootloader */ - palmz72_resume_info.resume_addr = (u32) pxa_cpu_resume; + palmz72_resume_info.resume_addr = (u32) cpu_resume; /* Storing memory touched by ROM */ store_ptr = *PALMZ72_SAVE_DWORD; diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 978e1b289544..51e1583265b2 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -33,7 +33,7 @@ int pxa_pm_enter(suspend_state_t state) #endif /* skip registers saving for standby */ - if (state != PM_SUSPEND_STANDBY) { + if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->save) { pxa_cpu_pm_fns->save(sleep_save); /* before sleeping, calculate and save a checksum */ for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++) @@ -44,7 +44,7 @@ int pxa_pm_enter(suspend_state_t state) pxa_cpu_pm_fns->enter(state); cpu_init(); - if (state != PM_SUSPEND_STANDBY) { + if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) { /* after sleeping, validate the checksum */ for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++) checksum += sleep_save[i]; @@ -67,11 +67,6 @@ int pxa_pm_enter(suspend_state_t state) EXPORT_SYMBOL_GPL(pxa_pm_enter); -unsigned long sleep_phys_sp(void *sp) -{ - return virt_to_phys(sp); -} - static int pxa_pm_valid(suspend_state_t state) { if (pxa_cpu_pm_fns) diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index fbc5b775f895..6bde5956358d 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -244,7 +244,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state) switch (state) { case PM_SUSPEND_MEM: - pxa25x_cpu_suspend(PWRMODE_SLEEP); + pxa25x_cpu_suspend(PWRMODE_SLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET); break; } } @@ -252,7 +252,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state) static int pxa25x_cpu_pm_prepare(void) { /* set resume return address */ - PSPR = virt_to_phys(pxa_cpu_resume); + PSPR = virt_to_phys(cpu_resume); return 0; } @@ -347,6 +347,7 @@ static struct platform_device *pxa25x_devices[] __initdata = { &pxa25x_device_assp, &pxa25x_device_pwm0, &pxa25x_device_pwm1, + &pxa_device_asoc_platform, }; static struct sys_device pxa25x_sysdev[] = { diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 987301ff4c33..28b11be00b3f 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -300,7 +300,7 @@ void pxa27x_cpu_pm_enter(suspend_state_t state) pxa_cpu_standby(); break; case PM_SUSPEND_MEM: - pxa27x_cpu_suspend(pwrmode); + pxa27x_cpu_suspend(pwrmode, PLAT_PHYS_OFFSET - PAGE_OFFSET); break; } } @@ -313,7 +313,7 @@ static int pxa27x_cpu_pm_valid(suspend_state_t state) static int pxa27x_cpu_pm_prepare(void) { /* set resume return address */ - PSPR = virt_to_phys(pxa_cpu_resume); + PSPR = virt_to_phys(cpu_resume); return 0; } diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index a7a19e1cd640..1230343d9c70 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -142,8 +142,7 @@ static void pxa3xx_cpu_pm_suspend(void) volatile unsigned long *p = (volatile void *)0xc0000000; unsigned long saved_data = *p; - extern void pxa3xx_cpu_suspend(void); - extern void pxa3xx_cpu_resume(void); + extern void pxa3xx_cpu_suspend(long); /* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */ CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM); @@ -161,9 +160,9 @@ static void pxa3xx_cpu_pm_suspend(void) PSPR = 0x5c014000; /* overwrite with the resume address */ - *p = virt_to_phys(pxa3xx_cpu_resume); + *p = virt_to_phys(cpu_resume); - pxa3xx_cpu_suspend(); + pxa3xx_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET); *p = saved_data; diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S index c551da86baf6..6f5368899d84 100644 --- a/arch/arm/mach-pxa/sleep.S +++ b/arch/arm/mach-pxa/sleep.S @@ -22,133 +22,26 @@ .text -pxa_cpu_save_cp: - @ get coprocessor registers - mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode - mrc p15, 0, r4, c15, c1, 0 @ CP access reg - mrc p15, 0, r5, c13, c0, 0 @ PID - mrc p15, 0, r6, c3, c0, 0 @ domain ID - mrc p15, 0, r7, c2, c0, 0 @ translation table base addr - mrc p15, 0, r8, c1, c1, 0 @ auxiliary control reg - mrc p15, 0, r9, c1, c0, 0 @ control reg - - bic r3, r3, #2 @ clear frequency change bit - - @ store them plus current virtual stack ptr on stack - mov r10, sp - stmfd sp!, {r3 - r10} - - mov pc, lr - -pxa_cpu_save_sp: - @ preserve phys address of stack - mov r0, sp - str lr, [sp, #-4]! - bl sleep_phys_sp - ldr r1, =sleep_save_sp - str r0, [r1] - ldr pc, [sp], #4 - #ifdef CONFIG_PXA3xx /* * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4) * - * NOTE: unfortunately, pxa_cpu_save_cp can not be reused here since - * the auxiliary control register address is different between pxa3xx - * and pxa{25x,27x} + * r0 = v:p offset */ - ENTRY(pxa3xx_cpu_suspend) #ifndef CONFIG_IWMMXT mra r2, r3, acc0 #endif stmfd sp!, {r2 - r12, lr} @ save registers on stack - - mrc p14, 0, r3, c6, c0, 0 @ clock configuration, for turbo mode - mrc p15, 0, r4, c15, c1, 0 @ CP access reg - mrc p15, 0, r5, c13, c0, 0 @ PID - mrc p15, 0, r6, c3, c0, 0 @ domain ID - mrc p15, 0, r7, c2, c0, 0 @ translation table base addr - mrc p15, 0, r8, c1, c0, 1 @ auxiliary control reg - mrc p15, 0, r9, c1, c0, 0 @ control reg - - bic r3, r3, #2 @ clear frequency change bit - - @ store them plus current virtual stack ptr on stack - mov r10, sp - stmfd sp!, {r3 - r10} - - @ store physical address of stack pointer - mov r0, sp - bl sleep_phys_sp - ldr r1, =sleep_save_sp - str r0, [r1] - - @ clean data cache - bl xsc3_flush_kern_cache_all + mov r1, r0 + ldr r3, =pxa_cpu_resume @ resume function + bl cpu_suspend mov r0, #0x06 @ S2D3C4 mode mcr p14, 0, r0, c7, c0, 0 @ enter sleep 20: b 20b @ waiting for sleep - - .data - .align 5 -/* - * pxa3xx_cpu_resume - */ - -ENTRY(pxa3xx_cpu_resume) - - mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off - msr cpsr_c, r0 - - ldr r0, sleep_save_sp @ stack phys addr - ldmfd r0, {r3 - r9, sp} @ CP regs + virt stack ptr - - mov r1, #0 - mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB - mcr p15, 0, r1, c7, c10, 4 @ drain write (&fill) buffer - mcr p15, 0, r1, c7, c5, 4 @ flush prefetch buffer - mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs - - mcr p14, 0, r3, c6, c0, 0 @ clock configuration, turbo mode. - mcr p15, 0, r4, c15, c1, 0 @ CP access reg - mcr p15, 0, r5, c13, c0, 0 @ PID - mcr p15, 0, r6, c3, c0, 0 @ domain ID - mcr p15, 0, r7, c2, c0, 0 @ translation table base addr - mcr p15, 0, r8, c1, c0, 1 @ auxiliary control reg - - @ temporarily map resume_turn_on_mmu into the page table, - @ otherwise prefetch abort occurs after MMU is turned on - mov r1, r7 - bic r1, r1, #0x00ff - bic r1, r1, #0x3f00 - ldr r2, =0x542e - - adr r3, resume_turn_on_mmu - mov r3, r3, lsr #20 - orr r4, r2, r3, lsl #20 - ldr r5, [r1, r3, lsl #2] - str r4, [r1, r3, lsl #2] - - @ Mapping page table address in the page table - mov r6, r1, lsr #20 - orr r7, r2, r6, lsl #20 - ldr r8, [r1, r6, lsl #2] - str r7, [r1, r6, lsl #2] - - ldr r2, =pxa3xx_resume_after_mmu @ absolute virtual address - b resume_turn_on_mmu @ cache align execution - - .text -pxa3xx_resume_after_mmu: - /* restore the temporary mapping */ - str r5, [r1, r3, lsl #2] - str r8, [r1, r6, lsl #2] - b resume_after_mmu - #endif /* CONFIG_PXA3xx */ #ifdef CONFIG_PXA27x @@ -158,28 +51,23 @@ pxa3xx_resume_after_mmu: * Forces CPU into sleep state. * * r0 = value for PWRMODE M field for desired sleep state + * r1 = v:p offset */ - ENTRY(pxa27x_cpu_suspend) #ifndef CONFIG_IWMMXT mra r2, r3, acc0 #endif stmfd sp!, {r2 - r12, lr} @ save registers on stack - - bl pxa_cpu_save_cp - - mov r5, r0 @ save sleep mode - bl pxa_cpu_save_sp - - @ clean data cache - bl xscale_flush_kern_cache_all + mov r4, r0 @ save sleep mode + ldr r3, =pxa_cpu_resume @ resume function + bl cpu_suspend @ Put the processor to sleep @ (also workaround for sighting 28071) @ prepare value for sleep mode - mov r1, r5 @ sleep mode + mov r1, r4 @ sleep mode @ prepare pointer to physical address 0 (virtual mapping in generic.c) mov r2, #UNCACHED_PHYS_0 @@ -216,21 +104,16 @@ ENTRY(pxa27x_cpu_suspend) * Forces CPU into sleep state. * * r0 = value for PWRMODE M field for desired sleep state + * r1 = v:p offset */ ENTRY(pxa25x_cpu_suspend) stmfd sp!, {r2 - r12, lr} @ save registers on stack - - bl pxa_cpu_save_cp - - mov r5, r0 @ save sleep mode - bl pxa_cpu_save_sp - - @ clean data cache - bl xscale_flush_kern_cache_all - + mov r4, r0 @ save sleep mode + ldr r3, =pxa_cpu_resume @ resume function + bl cpu_suspend @ prepare value for sleep mode - mov r1, r5 @ sleep mode + mov r1, r4 @ sleep mode @ prepare pointer to physical address 0 (virtual mapping in generic.c) mov r2, #UNCACHED_PHYS_0 @@ -317,53 +200,9 @@ pxa_cpu_do_suspend: * pxa_cpu_resume() * * entry point from bootloader into kernel during resume - * - * Note: Yes, part of the following code is located into the .data section. - * This is to allow sleep_save_sp to be accessed with a relative load - * while we can't rely on any MMU translation. We could have put - * sleep_save_sp in the .text section as well, but some setups might - * insist on it to be truly read-only. */ - - .data - .align 5 -ENTRY(pxa_cpu_resume) - mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off - msr cpsr_c, r0 - - ldr r0, sleep_save_sp @ stack phys addr - ldr r2, =resume_after_mmu @ its absolute virtual address - ldmfd r0, {r3 - r9, sp} @ CP regs + virt stack ptr - - mov r1, #0 - mcr p15, 0, r1, c8, c7, 0 @ invalidate I & D TLBs - mcr p15, 0, r1, c7, c7, 0 @ invalidate I & D caches, BTB - - mcr p14, 0, r3, c6, c0, 0 @ clock configuration, turbo mode. - mcr p15, 0, r4, c15, c1, 0 @ CP access reg - mcr p15, 0, r5, c13, c0, 0 @ PID - mcr p15, 0, r6, c3, c0, 0 @ domain ID - mcr p15, 0, r7, c2, c0, 0 @ translation table base addr - mcr p15, 0, r8, c1, c1, 0 @ auxiliary control reg - b resume_turn_on_mmu @ cache align execution - .align 5 -resume_turn_on_mmu: - mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, caches, etc. - - @ Let us ensure we jump to resume_after_mmu only when the mcr above - @ actually took effect. They call it the "cpwait" operation. - mrc p15, 0, r0, c2, c0, 0 @ queue a dependency on CP15 - sub pc, r2, r0, lsr #32 @ jump to virtual addr - nop - nop - nop - -sleep_save_sp: - .word 0 @ preserve stack phys ptr here - - .text -resume_after_mmu: +pxa_cpu_resume: ldmfd sp!, {r2, r3} #ifndef CONFIG_IWMMXT mar acc0, r2, r3 diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c index c31e601eb49c..b9b1e5c2b290 100644 --- a/arch/arm/mach-pxa/tosa-bt.c +++ b/arch/arm/mach-pxa/tosa-bt.c @@ -81,8 +81,6 @@ static int tosa_bt_probe(struct platform_device *dev) goto err_rfk_alloc; } - rfkill_set_led_trigger_name(rfk, "tosa-bt"); - rc = rfkill_register(rfk); if (rc) goto err_rfkill; diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index af152e70cfcf..f2582ec300d9 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -875,6 +875,11 @@ static struct platform_device sharpsl_rom_device = { .dev.platform_data = &sharpsl_rom_data, }; +static struct platform_device wm9712_device = { + .name = "wm9712-codec", + .id = -1, +}; + static struct platform_device *devices[] __initdata = { &tosascoop_device, &tosascoop_jc_device, @@ -885,6 +890,7 @@ static struct platform_device *devices[] __initdata = { &tosaled_device, &tosa_bt_device, &sharpsl_rom_device, + &wm9712_device, }; static void tosa_poweroff(void) diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index f4b053b35815..b92aa3b8c4f7 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -676,7 +676,7 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = { static void zeus_power_off(void) { local_irq_disable(); - pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP); + pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET); } #else #define zeus_power_off NULL diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index a0cb2581894f..50825a3f91cc 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig @@ -99,6 +99,7 @@ config MACH_NEO1973_GTA02 select POWER_SUPPLY select MACH_NEO1973 select S3C2410_PWM + select S3C_DEV_USB_HOST help Say Y here if you are using the Openmoko GTA02 / Freerunner GSM Phone diff --git a/arch/arm/mach-s3c2440/include/mach/gta02.h b/arch/arm/mach-s3c2440/include/mach/gta02.h index 953331d8d56a..3a56a229cac6 100644 --- a/arch/arm/mach-s3c2440/include/mach/gta02.h +++ b/arch/arm/mach-s3c2440/include/mach/gta02.h @@ -44,19 +44,19 @@ #define GTA02v3_GPIO_nUSB_FLT S3C2410_GPG(10) /* v3 + v4 only */ #define GTA02v3_GPIO_nGSM_OC S3C2410_GPG(11) /* v3 + v4 only */ -#define GTA02_GPIO_AMP_SHUT S3C2440_GPJ1 /* v2 + v3 + v4 only */ -#define GTA02v1_GPIO_WLAN_GPIO10 S3C2440_GPJ2 -#define GTA02_GPIO_HP_IN S3C2440_GPJ2 /* v2 + v3 + v4 only */ -#define GTA02_GPIO_INT0 S3C2440_GPJ3 /* v2 + v3 + v4 only */ -#define GTA02_GPIO_nGSM_EN S3C2440_GPJ4 -#define GTA02_GPIO_3D_RESET S3C2440_GPJ5 -#define GTA02_GPIO_nDL_GSM S3C2440_GPJ6 /* v4 + v5 only */ -#define GTA02_GPIO_WLAN_GPIO0 S3C2440_GPJ7 -#define GTA02v1_GPIO_BAT_ID S3C2440_GPJ8 -#define GTA02_GPIO_KEEPACT S3C2440_GPJ8 -#define GTA02v1_GPIO_HP_IN S3C2440_GPJ10 -#define GTA02_CHIP_PWD S3C2440_GPJ11 /* v2 + v3 + v4 only */ -#define GTA02_GPIO_nWLAN_RESET S3C2440_GPJ12 /* v2 + v3 + v4 only */ +#define GTA02_GPIO_AMP_SHUT S3C2410_GPJ(1) /* v2 + v3 + v4 only */ +#define GTA02v1_GPIO_WLAN_GPIO10 S3C2410_GPJ(2) +#define GTA02_GPIO_HP_IN S3C2410_GPJ(2) /* v2 + v3 + v4 only */ +#define GTA02_GPIO_INT0 S3C2410_GPJ(3) /* v2 + v3 + v4 only */ +#define GTA02_GPIO_nGSM_EN S3C2410_GPJ(4) +#define GTA02_GPIO_3D_RESET S3C2410_GPJ(5) +#define GTA02_GPIO_nDL_GSM S3C2410_GPJ(6) /* v4 + v5 only */ +#define GTA02_GPIO_WLAN_GPIO0 S3C2410_GPJ(7) +#define GTA02v1_GPIO_BAT_ID S3C2410_GPJ(8) +#define GTA02_GPIO_KEEPACT S3C2410_GPJ(8) +#define GTA02v1_GPIO_HP_IN S3C2410_GPJ(10) +#define GTA02_CHIP_PWD S3C2410_GPJ(11) /* v2 + v3 + v4 only */ +#define GTA02_GPIO_nWLAN_RESET S3C2410_GPJ(12) /* v2 + v3 + v4 only */ #define GTA02_IRQ_GSENSOR_1 IRQ_EINT0 #define GTA02_IRQ_MODEM IRQ_EINT1 diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index dd3782064508..fdfc4d5e37a1 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -151,6 +151,12 @@ static struct clk init_clocks_off[] = { .enable = s3c64xx_pclk_ctrl, .ctrlbit = S3C_CLKCON_PCLK_IIC, }, { + .name = "i2c", + .id = 1, + .parent = &clk_p, + .enable = s3c64xx_pclk_ctrl, + .ctrlbit = S3C6410_CLKCON_PCLK_I2C1, + }, { .name = "iis", .id = 0, .parent = &clk_p, diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c index 135db1b41252..c35585cf8c4f 100644 --- a/arch/arm/mach-s3c64xx/dma.c +++ b/arch/arm/mach-s3c64xx/dma.c @@ -690,12 +690,12 @@ static int s3c64xx_dma_init1(int chno, enum dma_ch chbase, regptr = regs + PL080_Cx_BASE(0); - for (ch = 0; ch < 8; ch++, chno++, chptr++) { - printk(KERN_INFO "%s: registering DMA %d (%p)\n", - __func__, chno, regptr); + for (ch = 0; ch < 8; ch++, chptr++) { + pr_debug("%s: registering DMA %d (%p)\n", + __func__, chno + ch, regptr); chptr->bit = 1 << ch; - chptr->number = chno; + chptr->number = chno + ch; chptr->dmac = dmac; chptr->regs = regptr; regptr += PL080_Cx_STRIDE; @@ -704,7 +704,8 @@ static int s3c64xx_dma_init1(int chno, enum dma_ch chbase, /* for the moment, permanently enable the controller */ writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG); - printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs); + printk(KERN_INFO "PL080: IRQ %d, at %p, channels %d..%d\n", + irq, regs, chno, chno+8); return 0; diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c index fd99a82e82c4..92b09085caaa 100644 --- a/arch/arm/mach-s3c64xx/gpiolib.c +++ b/arch/arm/mach-s3c64xx/gpiolib.c @@ -72,7 +72,7 @@ static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = { .get_pull = s3c_gpio_getpull_updown, }; -int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin) +static int s3c64xx_gpio2int_gpm(struct gpio_chip *chip, unsigned pin) { return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO; } @@ -138,7 +138,7 @@ static struct s3c_gpio_chip gpio_4bit[] = { }, }; -int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin) +static int s3c64xx_gpio2int_gpl(struct gpio_chip *chip, unsigned pin) { return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO; } diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index e85192a86fbe..a80a3163dd30 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -28,6 +28,7 @@ #include <linux/delay.h> #include <linux/smsc911x.h> #include <linux/regulator/fixed.h> +#include <linux/regulator/machine.h> #ifdef CONFIG_SMDK6410_WM1190_EV1 #include <linux/mfd/wm8350/core.h> @@ -351,7 +352,7 @@ static struct regulator_init_data smdk6410_vddpll = { /* VDD_UH_MMC, LDO5 on J5 */ static struct regulator_init_data smdk6410_vdduh_mmc = { .constraints = { - .name = "PVDD_UH/PVDD_MMC", + .name = "PVDD_UH+PVDD_MMC", .always_on = 1, }, }; @@ -417,7 +418,7 @@ static struct regulator_init_data smdk6410_vddaudio = { /* S3C64xx internal logic & PLL */ static struct regulator_init_data wm8350_dcdc1_data = { .constraints = { - .name = "PVDD_INT/PVDD_PLL", + .name = "PVDD_INT+PVDD_PLL", .min_uV = 1200000, .max_uV = 1200000, .always_on = 1, @@ -452,7 +453,7 @@ static struct regulator_consumer_supply wm8350_dcdc4_consumers[] = { static struct regulator_init_data wm8350_dcdc4_data = { .constraints = { - .name = "PVDD_HI/PVDD_EXT/PVDD_SYS/PVCCM2MTV", + .name = "PVDD_HI+PVDD_EXT+PVDD_SYS+PVCCM2MTV", .min_uV = 3000000, .max_uV = 3000000, .always_on = 1, @@ -464,7 +465,7 @@ static struct regulator_init_data wm8350_dcdc4_data = { /* OTGi/1190-EV1 HPVDD & AVDD */ static struct regulator_init_data wm8350_ldo4_data = { .constraints = { - .name = "PVDD_OTGI/HPVDD/AVDD", + .name = "PVDD_OTGI+HPVDD+AVDD", .min_uV = 1200000, .max_uV = 1200000, .apply_uV = 1, @@ -552,7 +553,7 @@ static struct wm831x_backlight_pdata wm1192_backlight_pdata = { static struct regulator_init_data wm1192_dcdc3 = { .constraints = { - .name = "PVDD_MEM/PVDD_GPS", + .name = "PVDD_MEM+PVDD_GPS", .always_on = 1, }, }; @@ -563,7 +564,7 @@ static struct regulator_consumer_supply wm1192_ldo1_consumers[] = { static struct regulator_init_data wm1192_ldo1 = { .constraints = { - .name = "PVDD_LCD/PVDD_EXT", + .name = "PVDD_LCD+PVDD_EXT", .always_on = 1, }, .consumer_supplies = wm1192_ldo1_consumers, diff --git a/arch/arm/mach-s3c64xx/setup-keypad.c b/arch/arm/mach-s3c64xx/setup-keypad.c index f8ed0d22db70..1d4d0ee9e870 100644 --- a/arch/arm/mach-s3c64xx/setup-keypad.c +++ b/arch/arm/mach-s3c64xx/setup-keypad.c @@ -17,7 +17,7 @@ void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols) { /* Set all the necessary GPK pins to special-function 3: KP_ROW[x] */ - s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), 8 + rows, S3C_GPIO_SFN(3)); + s3c_gpio_cfgrange_nopull(S3C64XX_GPK(8), rows, S3C_GPIO_SFN(3)); /* Set all the necessary GPL pins to special-function 3: KP_COL[x] */ s3c_gpio_cfgrange_nopull(S3C64XX_GPL(0), cols, S3C_GPIO_SFN(3)); diff --git a/arch/arm/mach-s3c64xx/setup-sdhci.c b/arch/arm/mach-s3c64xx/setup-sdhci.c index 1a942037c4ef..f344a222bc84 100644 --- a/arch/arm/mach-s3c64xx/setup-sdhci.c +++ b/arch/arm/mach-s3c64xx/setup-sdhci.c @@ -56,7 +56,7 @@ void s3c6400_setup_sdhci_cfg_card(struct platform_device *dev, else ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0); - printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3); + pr_debug("%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3); writel(ctrl2, r + S3C_SDHCI_CONTROL2); writel(ctrl3, r + S3C_SDHCI_CONTROL3); } diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S index b2ef44317368..afe5a762f46e 100644 --- a/arch/arm/mach-s3c64xx/sleep.S +++ b/arch/arm/mach-s3c64xx/sleep.S @@ -32,25 +32,13 @@ * code after resume. * * entry: - * r0 = pointer to the save block + * r1 = v:p offset */ ENTRY(s3c_cpu_save) stmfd sp!, { r4 - r12, lr } - - mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID - mrc p15, 0, r5, c3, c0, 0 @ Domain ID - mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 - mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 - mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control - mrc p15, 0, r9, c1, c0, 0 @ Control register - mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register - mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls - - stmia r0, { r4 - r13 } @ Save CP registers and SP - - @@ save our state to ram - bl s3c_pm_cb_flushcache + ldr r3, =resume_with_mmu + bl cpu_suspend @@ call final suspend code ldr r0, =pm_cpu_sleep @@ -61,18 +49,6 @@ ENTRY(s3c_cpu_save) resume_with_mmu: ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save - .data - - /* the next bit is code, but it requires easy access to the - * s3c_sleep_save_phys data before the MMU is switched on, so - * we store the code that needs this variable in the .data where - * the value can be written to (the .text segment is RO). - */ - - .global s3c_sleep_save_phys -s3c_sleep_save_phys: - .word 0 - /* Sleep magic, the word before the resume entry point so that the * bootloader can check for a resumeable image. */ @@ -110,35 +86,4 @@ ENTRY(s3c_cpu_resume) orr r0, r0, #1 << 15 @ GPN15 str r0, [ r3, #S3C64XX_GPNDAT ] #endif - - /* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches - * are thoroughly cleaned just in case the bootloader didn't do it - * for us. */ - mov r0, #0 - mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache - mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache - mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer - @@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs - @@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches - - ldr r0, s3c_sleep_save_phys - ldmia r0, { r4 - r13 } - - mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID - mcr p15, 0, r5, c3, c0, 0 @ Domain ID - mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 - mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 - mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control - mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register - - mov r0, #0 @ restore copro access controls - mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls - mcr p15, 0, r0, c7, c5, 4 - - ldr r2, =resume_with_mmu - mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */ - nop - mov pc, r2 /* jump back */ - - .end + b cpu_resume diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h index 203dd5a18bd5..058dab4482a1 100644 --- a/arch/arm/mach-s5p6442/include/mach/map.h +++ b/arch/arm/mach-s5p6442/include/mach/map.h @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s5p6442/include/mach/map.h * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * S5P6442 - Memory map definitions @@ -16,56 +16,61 @@ #include <plat/map-base.h> #include <plat/map-s5p.h> -#define S5P6442_PA_CHIPID (0xE0000000) -#define S5P_PA_CHIPID S5P6442_PA_CHIPID +#define S5P6442_PA_SDRAM 0x20000000 -#define S5P6442_PA_SYSCON (0xE0100000) -#define S5P_PA_SYSCON S5P6442_PA_SYSCON +#define S5P6442_PA_I2S0 0xC0B00000 +#define S5P6442_PA_I2S1 0xF2200000 -#define S5P6442_PA_GPIO (0xE0200000) +#define S5P6442_PA_CHIPID 0xE0000000 -#define S5P6442_PA_VIC0 (0xE4000000) -#define S5P6442_PA_VIC1 (0xE4100000) -#define S5P6442_PA_VIC2 (0xE4200000) +#define S5P6442_PA_SYSCON 0xE0100000 -#define S5P6442_PA_SROMC (0xE7000000) -#define S5P_PA_SROMC S5P6442_PA_SROMC +#define S5P6442_PA_GPIO 0xE0200000 -#define S5P6442_PA_MDMA 0xE8000000 -#define S5P6442_PA_PDMA 0xE9000000 +#define S5P6442_PA_VIC0 0xE4000000 +#define S5P6442_PA_VIC1 0xE4100000 +#define S5P6442_PA_VIC2 0xE4200000 -#define S5P6442_PA_TIMER (0xEA000000) -#define S5P_PA_TIMER S5P6442_PA_TIMER +#define S5P6442_PA_SROMC 0xE7000000 -#define S5P6442_PA_SYSTIMER (0xEA100000) +#define S5P6442_PA_MDMA 0xE8000000 +#define S5P6442_PA_PDMA 0xE9000000 -#define S5P6442_PA_WATCHDOG (0xEA200000) +#define S5P6442_PA_TIMER 0xEA000000 -#define S5P6442_PA_UART (0xEC000000) +#define S5P6442_PA_SYSTIMER 0xEA100000 -#define S5P_PA_UART0 (S5P6442_PA_UART + 0x0) -#define S5P_PA_UART1 (S5P6442_PA_UART + 0x400) -#define S5P_PA_UART2 (S5P6442_PA_UART + 0x800) -#define S5P_SZ_UART SZ_256 +#define S5P6442_PA_WATCHDOG 0xEA200000 -#define S5P6442_PA_IIC0 (0xEC100000) +#define S5P6442_PA_UART 0xEC000000 -#define S5P6442_PA_SDRAM (0x20000000) -#define S5P_PA_SDRAM S5P6442_PA_SDRAM +#define S5P6442_PA_IIC0 0xEC100000 #define S5P6442_PA_SPI 0xEC300000 -/* I2S */ -#define S5P6442_PA_I2S0 0xC0B00000 -#define S5P6442_PA_I2S1 0xF2200000 - -/* PCM */ #define S5P6442_PA_PCM0 0xF2400000 #define S5P6442_PA_PCM1 0xF2500000 -/* compatibiltiy defines. */ +/* Compatibiltiy Defines */ + +#define S3C_PA_IIC S5P6442_PA_IIC0 #define S3C_PA_WDT S5P6442_PA_WATCHDOG + +#define S5P_PA_CHIPID S5P6442_PA_CHIPID +#define S5P_PA_SDRAM S5P6442_PA_SDRAM +#define S5P_PA_SROMC S5P6442_PA_SROMC +#define S5P_PA_SYSCON S5P6442_PA_SYSCON +#define S5P_PA_TIMER S5P6442_PA_TIMER + +/* UART */ + #define S3C_PA_UART S5P6442_PA_UART -#define S3C_PA_IIC S5P6442_PA_IIC0 + +#define S5P_PA_UART(x) (S3C_PA_UART + ((x) * S3C_UART_OFFSET)) +#define S5P_PA_UART0 S5P_PA_UART(0) +#define S5P_PA_UART1 S5P_PA_UART(1) +#define S5P_PA_UART2 S5P_PA_UART(2) + +#define S5P_SZ_UART SZ_256 #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/gpio.h b/arch/arm/mach-s5p64x0/include/mach/gpio.h index 5486c8f01f1d..adb5f298ead8 100644 --- a/arch/arm/mach-s5p64x0/include/mach/gpio.h +++ b/arch/arm/mach-s5p64x0/include/mach/gpio.h @@ -23,7 +23,7 @@ #define S5P6440_GPIO_A_NR (6) #define S5P6440_GPIO_B_NR (7) #define S5P6440_GPIO_C_NR (8) -#define S5P6440_GPIO_F_NR (2) +#define S5P6440_GPIO_F_NR (16) #define S5P6440_GPIO_G_NR (7) #define S5P6440_GPIO_H_NR (10) #define S5P6440_GPIO_I_NR (16) @@ -36,7 +36,7 @@ #define S5P6450_GPIO_B_NR (7) #define S5P6450_GPIO_C_NR (8) #define S5P6450_GPIO_D_NR (8) -#define S5P6450_GPIO_F_NR (2) +#define S5P6450_GPIO_F_NR (16) #define S5P6450_GPIO_G_NR (14) #define S5P6450_GPIO_H_NR (10) #define S5P6450_GPIO_I_NR (16) diff --git a/arch/arm/mach-s5p64x0/include/mach/map.h b/arch/arm/mach-s5p64x0/include/mach/map.h index a9365e5ba614..95c91257c7ca 100644 --- a/arch/arm/mach-s5p64x0/include/mach/map.h +++ b/arch/arm/mach-s5p64x0/include/mach/map.h @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s5p64x0/include/mach/map.h * - * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd. + * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd. * http://www.samsung.com * * S5P64X0 - Memory map definitions @@ -16,64 +16,46 @@ #include <plat/map-base.h> #include <plat/map-s5p.h> -#define S5P64X0_PA_SDRAM (0x20000000) +#define S5P64X0_PA_SDRAM 0x20000000 -#define S5P64X0_PA_CHIPID (0xE0000000) -#define S5P_PA_CHIPID S5P64X0_PA_CHIPID - -#define S5P64X0_PA_SYSCON (0xE0100000) -#define S5P_PA_SYSCON S5P64X0_PA_SYSCON - -#define S5P64X0_PA_GPIO (0xE0308000) - -#define S5P64X0_PA_VIC0 (0xE4000000) -#define S5P64X0_PA_VIC1 (0xE4100000) +#define S5P64X0_PA_CHIPID 0xE0000000 -#define S5P64X0_PA_SROMC (0xE7000000) -#define S5P_PA_SROMC S5P64X0_PA_SROMC - -#define S5P64X0_PA_PDMA (0xE9000000) - -#define S5P64X0_PA_TIMER (0xEA000000) -#define S5P_PA_TIMER S5P64X0_PA_TIMER +#define S5P64X0_PA_SYSCON 0xE0100000 -#define S5P64X0_PA_RTC (0xEA100000) +#define S5P64X0_PA_GPIO 0xE0308000 -#define S5P64X0_PA_WDT (0xEA200000) +#define S5P64X0_PA_VIC0 0xE4000000 +#define S5P64X0_PA_VIC1 0xE4100000 -#define S5P6440_PA_UART(x) (0xEC000000 + ((x) * S3C_UART_OFFSET)) -#define S5P6450_PA_UART(x) ((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000)) +#define S5P64X0_PA_SROMC 0xE7000000 -#define S5P_PA_UART0 S5P6450_PA_UART(0) -#define S5P_PA_UART1 S5P6450_PA_UART(1) -#define S5P_PA_UART2 S5P6450_PA_UART(2) -#define S5P_PA_UART3 S5P6450_PA_UART(3) -#define S5P_PA_UART4 S5P6450_PA_UART(4) -#define S5P_PA_UART5 S5P6450_PA_UART(5) +#define S5P64X0_PA_PDMA 0xE9000000 -#define S5P_SZ_UART SZ_256 +#define S5P64X0_PA_TIMER 0xEA000000 +#define S5P64X0_PA_RTC 0xEA100000 +#define S5P64X0_PA_WDT 0xEA200000 -#define S5P6440_PA_IIC0 (0xEC104000) -#define S5P6440_PA_IIC1 (0xEC20F000) -#define S5P6450_PA_IIC0 (0xEC100000) -#define S5P6450_PA_IIC1 (0xEC200000) +#define S5P6440_PA_IIC0 0xEC104000 +#define S5P6440_PA_IIC1 0xEC20F000 +#define S5P6450_PA_IIC0 0xEC100000 +#define S5P6450_PA_IIC1 0xEC200000 -#define S5P64X0_PA_SPI0 (0xEC400000) -#define S5P64X0_PA_SPI1 (0xEC500000) +#define S5P64X0_PA_SPI0 0xEC400000 +#define S5P64X0_PA_SPI1 0xEC500000 -#define S5P64X0_PA_HSOTG (0xED100000) +#define S5P64X0_PA_HSOTG 0xED100000 #define S5P64X0_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000)) -#define S5P64X0_PA_I2S (0xF2000000) +#define S5P64X0_PA_I2S 0xF2000000 #define S5P6450_PA_I2S1 0xF2800000 #define S5P6450_PA_I2S2 0xF2900000 -#define S5P64X0_PA_PCM (0xF2100000) +#define S5P64X0_PA_PCM 0xF2100000 -#define S5P64X0_PA_ADC (0xF3000000) +#define S5P64X0_PA_ADC 0xF3000000 -/* compatibiltiy defines. */ +/* Compatibiltiy Defines */ #define S3C_PA_HSMMC0 S5P64X0_PA_HSMMC(0) #define S3C_PA_HSMMC1 S5P64X0_PA_HSMMC(1) @@ -83,6 +65,25 @@ #define S3C_PA_RTC S5P64X0_PA_RTC #define S3C_PA_WDT S5P64X0_PA_WDT +#define S5P_PA_CHIPID S5P64X0_PA_CHIPID +#define S5P_PA_SROMC S5P64X0_PA_SROMC +#define S5P_PA_SYSCON S5P64X0_PA_SYSCON +#define S5P_PA_TIMER S5P64X0_PA_TIMER + #define SAMSUNG_PA_ADC S5P64X0_PA_ADC +/* UART */ + +#define S5P6440_PA_UART(x) (0xEC000000 + ((x) * S3C_UART_OFFSET)) +#define S5P6450_PA_UART(x) ((x < 5) ? (0xEC800000 + ((x) * S3C_UART_OFFSET)) : (0xEC000000)) + +#define S5P_PA_UART0 S5P6450_PA_UART(0) +#define S5P_PA_UART1 S5P6450_PA_UART(1) +#define S5P_PA_UART2 S5P6450_PA_UART(2) +#define S5P_PA_UART3 S5P6450_PA_UART(3) +#define S5P_PA_UART4 S5P6450_PA_UART(4) +#define S5P_PA_UART5 S5P6450_PA_UART(5) + +#define S5P_SZ_UART SZ_256 + #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/map.h b/arch/arm/mach-s5pc100/include/mach/map.h index 328467b346aa..ccbe6b767f7d 100644 --- a/arch/arm/mach-s5pc100/include/mach/map.h +++ b/arch/arm/mach-s5pc100/include/mach/map.h @@ -1,5 +1,8 @@ /* linux/arch/arm/mach-s5pc100/include/mach/map.h * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * * Copyright 2009 Samsung Electronics Co. * Byungho Min <bhmin@samsung.com> * @@ -16,145 +19,115 @@ #include <plat/map-base.h> #include <plat/map-s5p.h> -/* - * map-base.h has already defined virtual memory address - * S3C_VA_IRQ S3C_ADDR(0x00000000) irq controller(s) - * S3C_VA_SYS S3C_ADDR(0x00100000) system control - * S3C_VA_MEM S3C_ADDR(0x00200000) system control (not used) - * S3C_VA_TIMER S3C_ADDR(0x00300000) timer block - * S3C_VA_WATCHDOG S3C_ADDR(0x00400000) watchdog - * S3C_VA_UART S3C_ADDR(0x01000000) UART - * - * S5PC100 specific virtual memory address can be defined here - * S5PC1XX_VA_GPIO S3C_ADDR(0x00500000) GPIO - * - */ +#define S5PC100_PA_SDRAM 0x20000000 + +#define S5PC100_PA_ONENAND 0xE7100000 +#define S5PC100_PA_ONENAND_BUF 0xB0000000 + +#define S5PC100_PA_CHIPID 0xE0000000 -#define S5PC100_PA_ONENAND_BUF (0xB0000000) -#define S5PC100_SZ_ONENAND_BUF (SZ_256M - SZ_32M) +#define S5PC100_PA_SYSCON 0xE0100000 -/* Chip ID */ +#define S5PC100_PA_OTHERS 0xE0200000 -#define S5PC100_PA_CHIPID (0xE0000000) -#define S5P_PA_CHIPID S5PC100_PA_CHIPID +#define S5PC100_PA_GPIO 0xE0300000 -#define S5PC100_PA_SYSCON (0xE0100000) -#define S5P_PA_SYSCON S5PC100_PA_SYSCON +#define S5PC100_PA_VIC0 0xE4000000 +#define S5PC100_PA_VIC1 0xE4100000 +#define S5PC100_PA_VIC2 0xE4200000 -#define S5PC100_PA_OTHERS (0xE0200000) -#define S5PC100_VA_OTHERS (S3C_VA_SYS + 0x10000) +#define S5PC100_PA_SROMC 0xE7000000 -#define S5PC100_PA_GPIO (0xE0300000) -#define S5PC1XX_VA_GPIO S3C_ADDR(0x00500000) +#define S5PC100_PA_CFCON 0xE7800000 -/* Interrupt */ -#define S5PC100_PA_VIC0 (0xE4000000) -#define S5PC100_PA_VIC1 (0xE4100000) -#define S5PC100_PA_VIC2 (0xE4200000) -#define S5PC100_VA_VIC S3C_VA_IRQ -#define S5PC100_VA_VIC_OFFSET 0x10000 -#define S5PC1XX_VA_VIC(x) (S5PC100_VA_VIC + ((x) * S5PC100_VA_VIC_OFFSET)) +#define S5PC100_PA_MDMA 0xE8100000 +#define S5PC100_PA_PDMA0 0xE9000000 +#define S5PC100_PA_PDMA1 0xE9200000 -#define S5PC100_PA_SROMC (0xE7000000) -#define S5P_PA_SROMC S5PC100_PA_SROMC +#define S5PC100_PA_TIMER 0xEA000000 +#define S5PC100_PA_SYSTIMER 0xEA100000 +#define S5PC100_PA_WATCHDOG 0xEA200000 +#define S5PC100_PA_RTC 0xEA300000 -#define S5PC100_PA_ONENAND (0xE7100000) +#define S5PC100_PA_UART 0xEC000000 -#define S5PC100_PA_CFCON (0xE7800000) +#define S5PC100_PA_IIC0 0xEC100000 +#define S5PC100_PA_IIC1 0xEC200000 -/* DMA */ -#define S5PC100_PA_MDMA (0xE8100000) -#define S5PC100_PA_PDMA0 (0xE9000000) -#define S5PC100_PA_PDMA1 (0xE9200000) +#define S5PC100_PA_SPI0 0xEC300000 +#define S5PC100_PA_SPI1 0xEC400000 +#define S5PC100_PA_SPI2 0xEC500000 -/* Timer */ -#define S5PC100_PA_TIMER (0xEA000000) -#define S5P_PA_TIMER S5PC100_PA_TIMER +#define S5PC100_PA_USB_HSOTG 0xED200000 +#define S5PC100_PA_USB_HSPHY 0xED300000 -#define S5PC100_PA_SYSTIMER (0xEA100000) +#define S5PC100_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000)) -#define S5PC100_PA_WATCHDOG (0xEA200000) -#define S5PC100_PA_RTC (0xEA300000) +#define S5PC100_PA_FB 0xEE000000 -#define S5PC100_PA_UART (0xEC000000) +#define S5PC100_PA_FIMC0 0xEE200000 +#define S5PC100_PA_FIMC1 0xEE300000 +#define S5PC100_PA_FIMC2 0xEE400000 -#define S5P_PA_UART0 (S5PC100_PA_UART + 0x0) -#define S5P_PA_UART1 (S5PC100_PA_UART + 0x400) -#define S5P_PA_UART2 (S5PC100_PA_UART + 0x800) -#define S5P_PA_UART3 (S5PC100_PA_UART + 0xC00) -#define S5P_SZ_UART SZ_256 +#define S5PC100_PA_I2S0 0xF2000000 +#define S5PC100_PA_I2S1 0xF2100000 +#define S5PC100_PA_I2S2 0xF2200000 -#define S5PC100_PA_IIC0 (0xEC100000) -#define S5PC100_PA_IIC1 (0xEC200000) +#define S5PC100_PA_AC97 0xF2300000 -/* SPI */ -#define S5PC100_PA_SPI0 0xEC300000 -#define S5PC100_PA_SPI1 0xEC400000 -#define S5PC100_PA_SPI2 0xEC500000 +#define S5PC100_PA_PCM0 0xF2400000 +#define S5PC100_PA_PCM1 0xF2500000 -/* USB HS OTG */ -#define S5PC100_PA_USB_HSOTG (0xED200000) -#define S5PC100_PA_USB_HSPHY (0xED300000) +#define S5PC100_PA_SPDIF 0xF2600000 -#define S5PC100_PA_FB (0xEE000000) +#define S5PC100_PA_TSADC 0xF3000000 -#define S5PC100_PA_FIMC0 (0xEE200000) -#define S5PC100_PA_FIMC1 (0xEE300000) -#define S5PC100_PA_FIMC2 (0xEE400000) +#define S5PC100_PA_KEYPAD 0xF3100000 -#define S5PC100_PA_I2S0 (0xF2000000) -#define S5PC100_PA_I2S1 (0xF2100000) -#define S5PC100_PA_I2S2 (0xF2200000) +/* Compatibiltiy Defines */ -#define S5PC100_PA_AC97 0xF2300000 +#define S3C_PA_FB S5PC100_PA_FB +#define S3C_PA_HSMMC0 S5PC100_PA_HSMMC(0) +#define S3C_PA_HSMMC1 S5PC100_PA_HSMMC(1) +#define S3C_PA_HSMMC2 S5PC100_PA_HSMMC(2) +#define S3C_PA_IIC S5PC100_PA_IIC0 +#define S3C_PA_IIC1 S5PC100_PA_IIC1 +#define S3C_PA_KEYPAD S5PC100_PA_KEYPAD +#define S3C_PA_ONENAND S5PC100_PA_ONENAND +#define S3C_PA_ONENAND_BUF S5PC100_PA_ONENAND_BUF +#define S3C_PA_RTC S5PC100_PA_RTC +#define S3C_PA_TSADC S5PC100_PA_TSADC +#define S3C_PA_USB_HSOTG S5PC100_PA_USB_HSOTG +#define S3C_PA_USB_HSPHY S5PC100_PA_USB_HSPHY +#define S3C_PA_WDT S5PC100_PA_WATCHDOG -/* PCM */ -#define S5PC100_PA_PCM0 0xF2400000 -#define S5PC100_PA_PCM1 0xF2500000 +#define S5P_PA_CHIPID S5PC100_PA_CHIPID +#define S5P_PA_FIMC0 S5PC100_PA_FIMC0 +#define S5P_PA_FIMC1 S5PC100_PA_FIMC1 +#define S5P_PA_FIMC2 S5PC100_PA_FIMC2 +#define S5P_PA_SDRAM S5PC100_PA_SDRAM +#define S5P_PA_SROMC S5PC100_PA_SROMC +#define S5P_PA_SYSCON S5PC100_PA_SYSCON +#define S5P_PA_TIMER S5PC100_PA_TIMER -#define S5PC100_PA_SPDIF 0xF2600000 +#define SAMSUNG_PA_ADC S5PC100_PA_TSADC +#define SAMSUNG_PA_CFCON S5PC100_PA_CFCON +#define SAMSUNG_PA_KEYPAD S5PC100_PA_KEYPAD -#define S5PC100_PA_TSADC (0xF3000000) +#define S5PC100_VA_OTHERS (S3C_VA_SYS + 0x10000) -/* KEYPAD */ -#define S5PC100_PA_KEYPAD (0xF3100000) +#define S3C_SZ_ONENAND_BUF (SZ_256M - SZ_32M) -#define S5PC100_PA_HSMMC(x) (0xED800000 + ((x) * 0x100000)) +/* UART */ -#define S5PC100_PA_SDRAM (0x20000000) -#define S5P_PA_SDRAM S5PC100_PA_SDRAM +#define S3C_PA_UART S5PC100_PA_UART -/* compatibiltiy defines. */ -#define S3C_PA_UART S5PC100_PA_UART -#define S3C_PA_IIC S5PC100_PA_IIC0 -#define S3C_PA_IIC1 S5PC100_PA_IIC1 -#define S3C_PA_FB S5PC100_PA_FB -#define S3C_PA_G2D S5PC100_PA_G2D -#define S3C_PA_G3D S5PC100_PA_G3D -#define S3C_PA_JPEG S5PC100_PA_JPEG -#define S3C_PA_ROTATOR S5PC100_PA_ROTATOR -#define S5P_VA_VIC0 S5PC1XX_VA_VIC(0) -#define S5P_VA_VIC1 S5PC1XX_VA_VIC(1) -#define S5P_VA_VIC2 S5PC1XX_VA_VIC(2) -#define S3C_PA_USB_HSOTG S5PC100_PA_USB_HSOTG -#define S3C_PA_USB_HSPHY S5PC100_PA_USB_HSPHY -#define S3C_PA_HSMMC0 S5PC100_PA_HSMMC(0) -#define S3C_PA_HSMMC1 S5PC100_PA_HSMMC(1) -#define S3C_PA_HSMMC2 S5PC100_PA_HSMMC(2) -#define S3C_PA_KEYPAD S5PC100_PA_KEYPAD -#define S3C_PA_WDT S5PC100_PA_WATCHDOG -#define S3C_PA_TSADC S5PC100_PA_TSADC -#define S3C_PA_ONENAND S5PC100_PA_ONENAND -#define S3C_PA_ONENAND_BUF S5PC100_PA_ONENAND_BUF -#define S3C_SZ_ONENAND_BUF S5PC100_SZ_ONENAND_BUF -#define S3C_PA_RTC S5PC100_PA_RTC - -#define SAMSUNG_PA_ADC S5PC100_PA_TSADC -#define SAMSUNG_PA_CFCON S5PC100_PA_CFCON -#define SAMSUNG_PA_KEYPAD S5PC100_PA_KEYPAD +#define S5P_PA_UART(x) (S3C_PA_UART + ((x) * S3C_UART_OFFSET)) +#define S5P_PA_UART0 S5P_PA_UART(0) +#define S5P_PA_UART1 S5P_PA_UART(1) +#define S5P_PA_UART2 S5P_PA_UART(2) +#define S5P_PA_UART3 S5P_PA_UART(3) -#define S5P_PA_FIMC0 S5PC100_PA_FIMC0 -#define S5P_PA_FIMC1 S5PC100_PA_FIMC1 -#define S5P_PA_FIMC2 S5PC100_PA_FIMC2 +#define S5P_SZ_UART SZ_256 -#endif /* __ASM_ARCH_C100_MAP_H */ +#endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index 3611492ad681..1dd58836fd4f 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s5pv210/include/mach/map.h * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * S5PV210 - Memory map definitions @@ -16,122 +16,120 @@ #include <plat/map-base.h> #include <plat/map-s5p.h> -#define S5PV210_PA_SROM_BANK5 (0xA8000000) +#define S5PV210_PA_SDRAM 0x20000000 -#define S5PC110_PA_ONENAND (0xB0000000) -#define S5P_PA_ONENAND S5PC110_PA_ONENAND +#define S5PV210_PA_SROM_BANK5 0xA8000000 -#define S5PC110_PA_ONENAND_DMA (0xB0600000) -#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA +#define S5PC110_PA_ONENAND 0xB0000000 +#define S5PC110_PA_ONENAND_DMA 0xB0600000 -#define S5PV210_PA_CHIPID (0xE0000000) -#define S5P_PA_CHIPID S5PV210_PA_CHIPID +#define S5PV210_PA_CHIPID 0xE0000000 -#define S5PV210_PA_SYSCON (0xE0100000) -#define S5P_PA_SYSCON S5PV210_PA_SYSCON +#define S5PV210_PA_SYSCON 0xE0100000 -#define S5PV210_PA_GPIO (0xE0200000) +#define S5PV210_PA_GPIO 0xE0200000 -/* SPI */ -#define S5PV210_PA_SPI0 0xE1300000 -#define S5PV210_PA_SPI1 0xE1400000 +#define S5PV210_PA_SPDIF 0xE1100000 -#define S5PV210_PA_KEYPAD (0xE1600000) +#define S5PV210_PA_SPI0 0xE1300000 +#define S5PV210_PA_SPI1 0xE1400000 -#define S5PV210_PA_IIC0 (0xE1800000) -#define S5PV210_PA_IIC1 (0xFAB00000) -#define S5PV210_PA_IIC2 (0xE1A00000) +#define S5PV210_PA_KEYPAD 0xE1600000 -#define S5PV210_PA_TIMER (0xE2500000) -#define S5P_PA_TIMER S5PV210_PA_TIMER +#define S5PV210_PA_ADC 0xE1700000 -#define S5PV210_PA_SYSTIMER (0xE2600000) +#define S5PV210_PA_IIC0 0xE1800000 +#define S5PV210_PA_IIC1 0xFAB00000 +#define S5PV210_PA_IIC2 0xE1A00000 -#define S5PV210_PA_WATCHDOG (0xE2700000) +#define S5PV210_PA_AC97 0xE2200000 -#define S5PV210_PA_RTC (0xE2800000) -#define S5PV210_PA_UART (0xE2900000) +#define S5PV210_PA_PCM0 0xE2300000 +#define S5PV210_PA_PCM1 0xE1200000 +#define S5PV210_PA_PCM2 0xE2B00000 -#define S5P_PA_UART0 (S5PV210_PA_UART + 0x0) -#define S5P_PA_UART1 (S5PV210_PA_UART + 0x400) -#define S5P_PA_UART2 (S5PV210_PA_UART + 0x800) -#define S5P_PA_UART3 (S5PV210_PA_UART + 0xC00) +#define S5PV210_PA_TIMER 0xE2500000 +#define S5PV210_PA_SYSTIMER 0xE2600000 +#define S5PV210_PA_WATCHDOG 0xE2700000 +#define S5PV210_PA_RTC 0xE2800000 -#define S5P_SZ_UART SZ_256 +#define S5PV210_PA_UART 0xE2900000 -#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) +#define S5PV210_PA_SROMC 0xE8000000 -#define S5PV210_PA_SROMC (0xE8000000) -#define S5P_PA_SROMC S5PV210_PA_SROMC +#define S5PV210_PA_CFCON 0xE8200000 -#define S5PV210_PA_CFCON (0xE8200000) +#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000)) -#define S5PV210_PA_MDMA 0xFA200000 -#define S5PV210_PA_PDMA0 0xE0900000 -#define S5PV210_PA_PDMA1 0xE0A00000 +#define S5PV210_PA_HSOTG 0xEC000000 +#define S5PV210_PA_HSPHY 0xEC100000 -#define S5PV210_PA_FB (0xF8000000) +#define S5PV210_PA_IIS0 0xEEE30000 +#define S5PV210_PA_IIS1 0xE2100000 +#define S5PV210_PA_IIS2 0xE2A00000 -#define S5PV210_PA_FIMC0 (0xFB200000) -#define S5PV210_PA_FIMC1 (0xFB300000) -#define S5PV210_PA_FIMC2 (0xFB400000) +#define S5PV210_PA_DMC0 0xF0000000 +#define S5PV210_PA_DMC1 0xF1400000 -#define S5PV210_PA_HSMMC(x) (0xEB000000 + ((x) * 0x100000)) +#define S5PV210_PA_VIC0 0xF2000000 +#define S5PV210_PA_VIC1 0xF2100000 +#define S5PV210_PA_VIC2 0xF2200000 +#define S5PV210_PA_VIC3 0xF2300000 -#define S5PV210_PA_HSOTG (0xEC000000) -#define S5PV210_PA_HSPHY (0xEC100000) +#define S5PV210_PA_FB 0xF8000000 -#define S5PV210_PA_VIC0 (0xF2000000) -#define S5PV210_PA_VIC1 (0xF2100000) -#define S5PV210_PA_VIC2 (0xF2200000) -#define S5PV210_PA_VIC3 (0xF2300000) +#define S5PV210_PA_MDMA 0xFA200000 +#define S5PV210_PA_PDMA0 0xE0900000 +#define S5PV210_PA_PDMA1 0xE0A00000 -#define S5PV210_PA_SDRAM (0x20000000) -#define S5P_PA_SDRAM S5PV210_PA_SDRAM +#define S5PV210_PA_MIPI_CSIS 0xFA600000 -/* S/PDIF */ -#define S5PV210_PA_SPDIF 0xE1100000 +#define S5PV210_PA_FIMC0 0xFB200000 +#define S5PV210_PA_FIMC1 0xFB300000 +#define S5PV210_PA_FIMC2 0xFB400000 -/* I2S */ -#define S5PV210_PA_IIS0 0xEEE30000 -#define S5PV210_PA_IIS1 0xE2100000 -#define S5PV210_PA_IIS2 0xE2A00000 +/* Compatibiltiy Defines */ -/* PCM */ -#define S5PV210_PA_PCM0 0xE2300000 -#define S5PV210_PA_PCM1 0xE1200000 -#define S5PV210_PA_PCM2 0xE2B00000 +#define S3C_PA_FB S5PV210_PA_FB +#define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0) +#define S3C_PA_HSMMC1 S5PV210_PA_HSMMC(1) +#define S3C_PA_HSMMC2 S5PV210_PA_HSMMC(2) +#define S3C_PA_HSMMC3 S5PV210_PA_HSMMC(3) +#define S3C_PA_IIC S5PV210_PA_IIC0 +#define S3C_PA_IIC1 S5PV210_PA_IIC1 +#define S3C_PA_IIC2 S5PV210_PA_IIC2 +#define S3C_PA_RTC S5PV210_PA_RTC +#define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG +#define S3C_PA_WDT S5PV210_PA_WATCHDOG -/* AC97 */ -#define S5PV210_PA_AC97 0xE2200000 +#define S5P_PA_CHIPID S5PV210_PA_CHIPID +#define S5P_PA_FIMC0 S5PV210_PA_FIMC0 +#define S5P_PA_FIMC1 S5PV210_PA_FIMC1 +#define S5P_PA_FIMC2 S5PV210_PA_FIMC2 +#define S5P_PA_MIPI_CSIS0 S5PV210_PA_MIPI_CSIS +#define S5P_PA_ONENAND S5PC110_PA_ONENAND +#define S5P_PA_ONENAND_DMA S5PC110_PA_ONENAND_DMA +#define S5P_PA_SDRAM S5PV210_PA_SDRAM +#define S5P_PA_SROMC S5PV210_PA_SROMC +#define S5P_PA_SYSCON S5PV210_PA_SYSCON +#define S5P_PA_TIMER S5PV210_PA_TIMER -#define S5PV210_PA_ADC (0xE1700000) +#define SAMSUNG_PA_ADC S5PV210_PA_ADC +#define SAMSUNG_PA_CFCON S5PV210_PA_CFCON +#define SAMSUNG_PA_KEYPAD S5PV210_PA_KEYPAD -#define S5PV210_PA_DMC0 (0xF0000000) -#define S5PV210_PA_DMC1 (0xF1400000) +/* UART */ -#define S5PV210_PA_MIPI_CSIS 0xFA600000 +#define S3C_VA_UARTx(x) (S3C_VA_UART + ((x) * S3C_UART_OFFSET)) -/* compatibiltiy defines. */ -#define S3C_PA_UART S5PV210_PA_UART -#define S3C_PA_HSMMC0 S5PV210_PA_HSMMC(0) -#define S3C_PA_HSMMC1 S5PV210_PA_HSMMC(1) -#define S3C_PA_HSMMC2 S5PV210_PA_HSMMC(2) -#define S3C_PA_HSMMC3 S5PV210_PA_HSMMC(3) -#define S3C_PA_IIC S5PV210_PA_IIC0 -#define S3C_PA_IIC1 S5PV210_PA_IIC1 -#define S3C_PA_IIC2 S5PV210_PA_IIC2 -#define S3C_PA_FB S5PV210_PA_FB -#define S3C_PA_RTC S5PV210_PA_RTC -#define S3C_PA_WDT S5PV210_PA_WATCHDOG -#define S3C_PA_USB_HSOTG S5PV210_PA_HSOTG -#define S5P_PA_FIMC0 S5PV210_PA_FIMC0 -#define S5P_PA_FIMC1 S5PV210_PA_FIMC1 -#define S5P_PA_FIMC2 S5PV210_PA_FIMC2 -#define S5P_PA_MIPI_CSIS0 S5PV210_PA_MIPI_CSIS +#define S3C_PA_UART S5PV210_PA_UART -#define SAMSUNG_PA_ADC S5PV210_PA_ADC -#define SAMSUNG_PA_CFCON S5PV210_PA_CFCON -#define SAMSUNG_PA_KEYPAD S5PV210_PA_KEYPAD +#define S5P_PA_UART(x) (S3C_PA_UART + ((x) * S3C_UART_OFFSET)) +#define S5P_PA_UART0 S5P_PA_UART(0) +#define S5P_PA_UART1 S5P_PA_UART(1) +#define S5P_PA_UART2 S5P_PA_UART(2) +#define S5P_PA_UART3 S5P_PA_UART(3) + +#define S5P_SZ_UART SZ_256 #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c index 461aa035afc0..557add4fc56c 100644 --- a/arch/arm/mach-s5pv210/mach-aquila.c +++ b/arch/arm/mach-s5pv210/mach-aquila.c @@ -149,7 +149,7 @@ static struct regulator_init_data aquila_ldo2_data = { static struct regulator_init_data aquila_ldo3_data = { .constraints = { - .name = "VUSB/MIPI_1.1V", + .name = "VUSB+MIPI_1.1V", .min_uV = 1100000, .max_uV = 1100000, .apply_uV = 1, @@ -197,7 +197,7 @@ static struct regulator_init_data aquila_ldo7_data = { static struct regulator_init_data aquila_ldo8_data = { .constraints = { - .name = "VUSB/VADC_3.3V", + .name = "VUSB+VADC_3.3V", .min_uV = 3300000, .max_uV = 3300000, .apply_uV = 1, @@ -207,7 +207,7 @@ static struct regulator_init_data aquila_ldo8_data = { static struct regulator_init_data aquila_ldo9_data = { .constraints = { - .name = "VCC/VCAM_2.8V", + .name = "VCC+VCAM_2.8V", .min_uV = 2800000, .max_uV = 2800000, .apply_uV = 1, @@ -381,9 +381,12 @@ static struct max8998_platform_data aquila_max8998_pdata = { .buck1_set1 = S5PV210_GPH0(3), .buck1_set2 = S5PV210_GPH0(4), .buck2_set3 = S5PV210_GPH0(5), - .buck1_max_voltage1 = 1200000, - .buck1_max_voltage2 = 1200000, - .buck2_max_voltage = 1200000, + .buck1_voltage1 = 1200000, + .buck1_voltage2 = 1200000, + .buck1_voltage3 = 1200000, + .buck1_voltage4 = 1200000, + .buck2_voltage1 = 1200000, + .buck2_voltage2 = 1200000, }; #endif diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c index e22d5112fd44..056f5c769b0a 100644 --- a/arch/arm/mach-s5pv210/mach-goni.c +++ b/arch/arm/mach-s5pv210/mach-goni.c @@ -288,7 +288,7 @@ static struct regulator_init_data goni_ldo2_data = { static struct regulator_init_data goni_ldo3_data = { .constraints = { - .name = "VUSB/MIPI_1.1V", + .name = "VUSB+MIPI_1.1V", .min_uV = 1100000, .max_uV = 1100000, .apply_uV = 1, @@ -337,7 +337,7 @@ static struct regulator_init_data goni_ldo7_data = { static struct regulator_init_data goni_ldo8_data = { .constraints = { - .name = "VUSB/VADC_3.3V", + .name = "VUSB+VADC_3.3V", .min_uV = 3300000, .max_uV = 3300000, .apply_uV = 1, @@ -347,7 +347,7 @@ static struct regulator_init_data goni_ldo8_data = { static struct regulator_init_data goni_ldo9_data = { .constraints = { - .name = "VCC/VCAM_2.8V", + .name = "VCC+VCAM_2.8V", .min_uV = 2800000, .max_uV = 2800000, .apply_uV = 1, @@ -521,9 +521,12 @@ static struct max8998_platform_data goni_max8998_pdata = { .buck1_set1 = S5PV210_GPH0(3), .buck1_set2 = S5PV210_GPH0(4), .buck2_set3 = S5PV210_GPH0(5), - .buck1_max_voltage1 = 1200000, - .buck1_max_voltage2 = 1200000, - .buck2_max_voltage = 1200000, + .buck1_voltage1 = 1200000, + .buck1_voltage2 = 1200000, + .buck1_voltage3 = 1200000, + .buck1_voltage4 = 1200000, + .buck2_voltage1 = 1200000, + .buck2_voltage2 = 1200000, }; #endif diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S index d4d222b716b4..a3d649466fb1 100644 --- a/arch/arm/mach-s5pv210/sleep.S +++ b/arch/arm/mach-s5pv210/sleep.S @@ -35,50 +35,24 @@ /* s3c_cpu_save * * entry: - * r0 = save address (virtual addr of s3c_sleep_save_phys) + * r1 = v:p offset */ ENTRY(s3c_cpu_save) stmfd sp!, { r3 - r12, lr } - - mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID - mrc p15, 0, r5, c3, c0, 0 @ Domain ID - mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 - mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 - mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control - mrc p15, 0, r9, c1, c0, 0 @ Control register - mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register - mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls - mrc p15, 0, r12, c10, c2, 0 @ Read PRRR - mrc p15, 0, r3, c10, c2, 1 @ READ NMRR - - stmia r0, { r3 - r13 } - - bl s3c_pm_cb_flushcache + ldr r3, =resume_with_mmu + bl cpu_suspend ldr r0, =pm_cpu_sleep ldr r0, [ r0 ] mov pc, r0 resume_with_mmu: - /* - * After MMU is turned on, restore the previous MMU table. - */ - ldr r9 , =(PAGE_OFFSET - PHYS_OFFSET) - add r4, r4, r9 - str r12, [r4] - ldmfd sp!, { r3 - r12, pc } .ltorg - .data - - .global s3c_sleep_save_phys -s3c_sleep_save_phys: - .word 0 - /* sleep magic, to allow the bootloader to check for an valid * image to resume to. Must be the first word before the * s3c_cpu_resume entry. @@ -96,75 +70,4 @@ s3c_sleep_save_phys: */ ENTRY(s3c_cpu_resume) - mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE - msr cpsr_c, r0 - - mov r1, #0 - mcr p15, 0, r1, c8, c7, 0 @ invalidate TLBs - mcr p15, 0, r1, c7, c5, 0 @ invalidate I Cache - - ldr r0, s3c_sleep_save_phys @ address of restore block - ldmia r0, { r3 - r13 } - - mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID - mcr p15, 0, r5, c3, c0, 0 @ Domain ID - - mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control - mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1 - mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0 - - mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register - - mov r0, #0 - mcr p15, 0, r0, c8, c7, 0 @ Invalidate I & D TLB - - mov r0, #0 @ restore copro access - mcr p15, 0, r11, c1, c0, 2 @ Co-processor access - mcr p15, 0, r0, c7, c5, 4 - - mcr p15, 0, r12, c10, c2, 0 @ write PRRR - mcr p15, 0, r3, c10, c2, 1 @ write NMRR - - /* - * In Cortex-A8, when MMU is turned on, the pipeline is flushed. - * And there are no valid entries in the MMU table at this point. - * So before turning on the MMU, the MMU entry for the DRAM address - * range is added. After the MMU is turned on, the other entries - * in the MMU table will be restored. - */ - - /* r6 = Translation Table BASE0 */ - mov r4, r6 - mov r4, r4, LSR #14 - mov r4, r4, LSL #14 - - /* Load address for adding to MMU table list */ - ldr r11, =0xE010F000 @ INFORM0 reg. - ldr r10, [r11, #0] - mov r10, r10, LSR #18 - bic r10, r10, #0x3 - orr r4, r4, r10 - - /* Calculate MMU table entry */ - mov r10, r10, LSL #18 - ldr r5, =0x40E - orr r10, r10, r5 - - /* Back up originally data */ - ldr r12, [r4] - - /* Add calculated MMU table entry into MMU table list */ - str r10, [r4] - - ldr r2, =resume_with_mmu - mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc - - nop - nop - nop - nop - nop @ second-to-last before mmu - - mov pc, r2 @ go back to virtual address - - .ltorg + b cpu_resume diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig index 09c4c21b70cc..b2a9acc5185f 100644 --- a/arch/arm/mach-s5pv310/Kconfig +++ b/arch/arm/mach-s5pv310/Kconfig @@ -122,6 +122,7 @@ config MACH_SMDKV310 select S3C_DEV_HSMMC2 select S3C_DEV_HSMMC3 select S5PV310_DEV_PD + select S5PV310_DEV_SYSMMU select S5PV310_SETUP_I2C1 select S5PV310_SETUP_SDHCI help diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h index 74d400625a23..901657fa7a12 100644 --- a/arch/arm/mach-s5pv310/include/mach/map.h +++ b/arch/arm/mach-s5pv310/include/mach/map.h @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s5pv310/include/mach/map.h * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * S5PV310 - Memory map definitions @@ -23,90 +23,43 @@ #include <plat/map-s5p.h> -#define S5PV310_PA_SYSRAM (0x02025000) +#define S5PV310_PA_SYSRAM 0x02025000 -#define S5PV310_PA_SROM_BANK(x) (0x04000000 + ((x) * 0x01000000)) - -#define S5PC210_PA_ONENAND (0x0C000000) -#define S5P_PA_ONENAND S5PC210_PA_ONENAND - -#define S5PC210_PA_ONENAND_DMA (0x0C600000) -#define S5P_PA_ONENAND_DMA S5PC210_PA_ONENAND_DMA - -#define S5PV310_PA_CHIPID (0x10000000) -#define S5P_PA_CHIPID S5PV310_PA_CHIPID - -#define S5PV310_PA_SYSCON (0x10010000) -#define S5P_PA_SYSCON S5PV310_PA_SYSCON +#define S5PV310_PA_I2S0 0x03830000 +#define S5PV310_PA_I2S1 0xE3100000 +#define S5PV310_PA_I2S2 0xE2A00000 -#define S5PV310_PA_PMU (0x10020000) +#define S5PV310_PA_PCM0 0x03840000 +#define S5PV310_PA_PCM1 0x13980000 +#define S5PV310_PA_PCM2 0x13990000 -#define S5PV310_PA_CMU (0x10030000) - -#define S5PV310_PA_WATCHDOG (0x10060000) -#define S5PV310_PA_RTC (0x10070000) - -#define S5PV310_PA_DMC0 (0x10400000) - -#define S5PV310_PA_COMBINER (0x10448000) - -#define S5PV310_PA_COREPERI (0x10500000) -#define S5PV310_PA_GIC_CPU (0x10500100) -#define S5PV310_PA_TWD (0x10500600) -#define S5PV310_PA_GIC_DIST (0x10501000) -#define S5PV310_PA_L2CC (0x10502000) - -/* DMA */ -#define S5PV310_PA_MDMA 0x10810000 -#define S5PV310_PA_PDMA0 0x12680000 -#define S5PV310_PA_PDMA1 0x12690000 - -#define S5PV310_PA_GPIO1 (0x11400000) -#define S5PV310_PA_GPIO2 (0x11000000) -#define S5PV310_PA_GPIO3 (0x03860000) - -#define S5PV310_PA_MIPI_CSIS0 0x11880000 -#define S5PV310_PA_MIPI_CSIS1 0x11890000 +#define S5PV310_PA_SROM_BANK(x) (0x04000000 + ((x) * 0x01000000)) -#define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000)) +#define S5PC210_PA_ONENAND 0x0C000000 +#define S5PC210_PA_ONENAND_DMA 0x0C600000 -#define S5PV310_PA_SROMC (0x12570000) -#define S5P_PA_SROMC S5PV310_PA_SROMC +#define S5PV310_PA_CHIPID 0x10000000 -/* S/PDIF */ -#define S5PV310_PA_SPDIF 0xE1100000 +#define S5PV310_PA_SYSCON 0x10010000 +#define S5PV310_PA_PMU 0x10020000 +#define S5PV310_PA_CMU 0x10030000 -/* I2S */ -#define S5PV310_PA_I2S0 0x03830000 -#define S5PV310_PA_I2S1 0xE3100000 -#define S5PV310_PA_I2S2 0xE2A00000 +#define S5PV310_PA_WATCHDOG 0x10060000 +#define S5PV310_PA_RTC 0x10070000 -/* PCM */ -#define S5PV310_PA_PCM0 0x03840000 -#define S5PV310_PA_PCM1 0x13980000 -#define S5PV310_PA_PCM2 0x13990000 +#define S5PV310_PA_DMC0 0x10400000 -/* AC97 */ -#define S5PV310_PA_AC97 0x139A0000 +#define S5PV310_PA_COMBINER 0x10448000 -#define S5PV310_PA_UART (0x13800000) +#define S5PV310_PA_COREPERI 0x10500000 +#define S5PV310_PA_GIC_CPU 0x10500100 +#define S5PV310_PA_TWD 0x10500600 +#define S5PV310_PA_GIC_DIST 0x10501000 +#define S5PV310_PA_L2CC 0x10502000 -#define S5P_PA_UART(x) (S5PV310_PA_UART + ((x) * S3C_UART_OFFSET)) -#define S5P_PA_UART0 S5P_PA_UART(0) -#define S5P_PA_UART1 S5P_PA_UART(1) -#define S5P_PA_UART2 S5P_PA_UART(2) -#define S5P_PA_UART3 S5P_PA_UART(3) -#define S5P_PA_UART4 S5P_PA_UART(4) - -#define S5P_SZ_UART SZ_256 - -#define S5PV310_PA_IIC(x) (0x13860000 + ((x) * 0x10000)) - -#define S5PV310_PA_TIMER (0x139D0000) -#define S5P_PA_TIMER S5PV310_PA_TIMER - -#define S5PV310_PA_SDRAM (0x40000000) -#define S5P_PA_SDRAM S5PV310_PA_SDRAM +#define S5PV310_PA_MDMA 0x10810000 +#define S5PV310_PA_PDMA0 0x12680000 +#define S5PV310_PA_PDMA1 0x12690000 #define S5PV310_PA_SYSMMU_MDMA 0x10A40000 #define S5PV310_PA_SYSMMU_SSS 0x10A50000 @@ -124,11 +77,32 @@ #define S5PV310_PA_SYSMMU_TV 0x12E20000 #define S5PV310_PA_SYSMMU_MFC_L 0x13620000 #define S5PV310_PA_SYSMMU_MFC_R 0x13630000 -#define S5PV310_SYSMMU_TOTAL_IPNUM 16 -#define S5P_SYSMMU_TOTAL_IPNUM S5PV310_SYSMMU_TOTAL_IPNUM -/* compatibiltiy defines. */ -#define S3C_PA_UART S5PV310_PA_UART +#define S5PV310_PA_GPIO1 0x11400000 +#define S5PV310_PA_GPIO2 0x11000000 +#define S5PV310_PA_GPIO3 0x03860000 + +#define S5PV310_PA_MIPI_CSIS0 0x11880000 +#define S5PV310_PA_MIPI_CSIS1 0x11890000 + +#define S5PV310_PA_HSMMC(x) (0x12510000 + ((x) * 0x10000)) + +#define S5PV310_PA_SROMC 0x12570000 + +#define S5PV310_PA_UART 0x13800000 + +#define S5PV310_PA_IIC(x) (0x13860000 + ((x) * 0x10000)) + +#define S5PV310_PA_AC97 0x139A0000 + +#define S5PV310_PA_TIMER 0x139D0000 + +#define S5PV310_PA_SDRAM 0x40000000 + +#define S5PV310_PA_SPDIF 0xE1100000 + +/* Compatibiltiy Defines */ + #define S3C_PA_HSMMC0 S5PV310_PA_HSMMC(0) #define S3C_PA_HSMMC1 S5PV310_PA_HSMMC(1) #define S3C_PA_HSMMC2 S5PV310_PA_HSMMC(2) @@ -143,7 +117,28 @@ #define S3C_PA_IIC7 S5PV310_PA_IIC(7) #define S3C_PA_RTC S5PV310_PA_RTC #define S3C_PA_WDT S5PV310_PA_WATCHDOG + +#define S5P_PA_CHIPID S5PV310_PA_CHIPID #define S5P_PA_MIPI_CSIS0 S5PV310_PA_MIPI_CSIS0 #define S5P_PA_MIPI_CSIS1 S5PV310_PA_MIPI_CSIS1 +#define S5P_PA_ONENAND S5PC210_PA_ONENAND +#define S5P_PA_ONENAND_DMA S5PC210_PA_ONENAND_DMA +#define S5P_PA_SDRAM S5PV310_PA_SDRAM +#define S5P_PA_SROMC S5PV310_PA_SROMC +#define S5P_PA_SYSCON S5PV310_PA_SYSCON +#define S5P_PA_TIMER S5PV310_PA_TIMER + +/* UART */ + +#define S3C_PA_UART S5PV310_PA_UART + +#define S5P_PA_UART(x) (S3C_PA_UART + ((x) * S3C_UART_OFFSET)) +#define S5P_PA_UART0 S5P_PA_UART(0) +#define S5P_PA_UART1 S5P_PA_UART(1) +#define S5P_PA_UART2 S5P_PA_UART(2) +#define S5P_PA_UART3 S5P_PA_UART(3) +#define S5P_PA_UART4 S5P_PA_UART(4) + +#define S5P_SZ_UART SZ_256 #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s5pv310/include/mach/sysmmu.h b/arch/arm/mach-s5pv310/include/mach/sysmmu.h index 662fe85ff4d5..598fc5c9211b 100644 --- a/arch/arm/mach-s5pv310/include/mach/sysmmu.h +++ b/arch/arm/mach-s5pv310/include/mach/sysmmu.h @@ -13,6 +13,9 @@ #ifndef __ASM_ARM_ARCH_SYSMMU_H #define __ASM_ARM_ARCH_SYSMMU_H __FILE__ +#define S5PV310_SYSMMU_TOTAL_IPNUM 16 +#define S5P_SYSMMU_TOTAL_IPNUM S5PV310_SYSMMU_TOTAL_IPNUM + enum s5pv310_sysmmu_ips { SYSMMU_MDMA, SYSMMU_SSS, @@ -32,7 +35,7 @@ enum s5pv310_sysmmu_ips { SYSMMU_MFC_R, }; -static char *sysmmu_ips_name[S5P_SYSMMU_TOTAL_IPNUM] = { +static char *sysmmu_ips_name[S5PV310_SYSMMU_TOTAL_IPNUM] = { "SYSMMU_MDMA" , "SYSMMU_SSS" , "SYSMMU_FIMC0" , diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index d43c5ef58eb6..bd3e1bfdd6aa 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -241,6 +241,9 @@ static struct locomo_platform_data locomo_info = { struct platform_device collie_locomo_device = { .name = "locomo", .id = 0, + .dev = { + .platform_data = &locomo_info, + }, .num_resources = ARRAY_SIZE(locomo_resources), .resource = locomo_resources, }; diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index ab9fc4470d36..c4661aab22fb 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -32,8 +32,7 @@ #include <asm/system.h> #include <asm/mach/time.h> -extern void sa1100_cpu_suspend(void); -extern void sa1100_cpu_resume(void); +extern void sa1100_cpu_suspend(long); #define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] @@ -73,10 +72,10 @@ static int sa11x0_pm_enter(suspend_state_t state) RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR; /* set resume return address */ - PSPR = virt_to_phys(sa1100_cpu_resume); + PSPR = virt_to_phys(cpu_resume); /* go zzz */ - sa1100_cpu_suspend(); + sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET); cpu_init(); @@ -115,11 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state) return 0; } -unsigned long sleep_phys_sp(void *sp) -{ - return virt_to_phys(sp); -} - static const struct platform_suspend_ops sa11x0_pm_ops = { .enter = sa11x0_pm_enter, .valid = suspend_valid_only_mem, diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index 80f31bad707c..04f2a618d4ef 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S @@ -20,12 +20,7 @@ #include <asm/assembler.h> #include <mach/hardware.h> - - .text - - - /* * sa1100_cpu_suspend() * @@ -34,27 +29,10 @@ */ ENTRY(sa1100_cpu_suspend) - stmfd sp!, {r4 - r12, lr} @ save registers on stack - - @ get coprocessor registers - mrc p15, 0, r4, c3, c0, 0 @ domain ID - mrc p15, 0, r5, c2, c0, 0 @ translation table base addr - mrc p15, 0, r6, c13, c0, 0 @ PID - mrc p15, 0, r7, c1, c0, 0 @ control reg - - @ store them plus current virtual stack ptr on stack - mov r8, sp - stmfd sp!, {r4 - r8} - - @ preserve phys address of stack - mov r0, sp - bl sleep_phys_sp - ldr r1, =sleep_save_sp - str r0, [r1] - - @ clean data cache and invalidate WB - bl v4wb_flush_kern_cache_all + mov r1, r0 + ldr r3, =sa1100_cpu_resume @ return function + bl cpu_suspend @ disable clock switching mcr p15, 0, r1, c15, c2, 2 @@ -166,50 +144,8 @@ sa1110_sdram_controller_fix: * cpu_sa1100_resume() * * entry point from bootloader into kernel during resume - * - * Note: Yes, part of the following code is located into the .data section. - * This is to allow sleep_save_sp to be accessed with a relative load - * while we can't rely on any MMU translation. We could have put - * sleep_save_sp in the .text section as well, but some setups might - * insist on it to be truly read-only. */ - - .data - .align 5 -ENTRY(sa1100_cpu_resume) - mov r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, r0 @ set SVC, irqs off - - ldr r0, sleep_save_sp @ stack phys addr - ldr r2, =resume_after_mmu @ its absolute virtual address - ldmfd r0, {r4 - r7, sp} @ CP regs + virt stack ptr - - mov r1, #0 - mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs - mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache - mcr p15, 0, r1, c9, c0, 0 @ invalidate RB - mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB - - mcr p15, 0, r4, c3, c0, 0 @ domain ID - mcr p15, 0, r5, c2, c0, 0 @ translation table base addr - mcr p15, 0, r6, c13, c0, 0 @ PID - b resume_turn_on_mmu @ cache align execution - .align 5 -resume_turn_on_mmu: - mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, caches, etc. - nop - mov pc, r2 @ jump to virtual addr - nop - nop - nop - -sleep_save_sp: - .word 0 @ preserve stack phys ptr here - - .text -resume_after_mmu: +sa1100_cpu_resume: mcr p15, 0, r1, c15, c1, 2 @ enable clock switching ldmfd sp!, {r4 - r12, pc} @ return to caller - - diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 4d1b4c5c9389..0c8f6cf3e948 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -60,6 +60,8 @@ endchoice config MACH_AG5EVM bool "AG5EVM board" + select ARCH_REQUIRE_GPIOLIB + select SH_LCD_MIPI_DSI depends on ARCH_SH73A0 config MACH_MACKEREL diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index c18a740a4159..4303a86e6e38 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -34,9 +34,10 @@ #include <linux/input/sh_keysc.h> #include <linux/mmc/host.h> #include <linux/mmc/sh_mmcif.h> - +#include <linux/sh_clk.h> +#include <video/sh_mobile_lcdc.h> +#include <video/sh_mipi_dsi.h> #include <sound/sh_fsi.h> - #include <mach/hardware.h> #include <mach/sh73a0.h> #include <mach/common.h> @@ -183,11 +184,165 @@ static struct platform_device mmc_device = { .resource = sh_mmcif_resources, }; +/* IrDA */ +static struct resource irda_resources[] = { + [0] = { + .start = 0xE6D00000, + .end = 0xE6D01FD4 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gic_spi(95), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device irda_device = { + .name = "sh_irda", + .id = 0, + .resource = irda_resources, + .num_resources = ARRAY_SIZE(irda_resources), +}; + +static unsigned char lcd_backlight_seq[3][2] = { + { 0x04, 0x07 }, + { 0x23, 0x80 }, + { 0x03, 0x01 }, +}; + +static void lcd_backlight_on(void) +{ + struct i2c_adapter *a; + struct i2c_msg msg; + int k; + + a = i2c_get_adapter(1); + for (k = 0; a && k < 3; k++) { + msg.addr = 0x6d; + msg.buf = &lcd_backlight_seq[k][0]; + msg.len = 2; + msg.flags = 0; + if (i2c_transfer(a, &msg, 1) != 1) + break; + } +} + +static void lcd_backlight_reset(void) +{ + gpio_set_value(GPIO_PORT235, 0); + mdelay(24); + gpio_set_value(GPIO_PORT235, 1); +} + +static void lcd_on(void *board_data, struct fb_info *info) +{ + lcd_backlight_on(); +} + +static void lcd_off(void *board_data) +{ + lcd_backlight_reset(); +} + +/* LCDC0 */ +static const struct fb_videomode lcdc0_modes[] = { + { + .name = "R63302(QHD)", + .xres = 544, + .yres = 961, + .left_margin = 72, + .right_margin = 600, + .hsync_len = 16, + .upper_margin = 8, + .lower_margin = 8, + .vsync_len = 2, + .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, + }, +}; + +static struct sh_mobile_lcdc_info lcdc0_info = { + .clock_source = LCDC_CLK_PERIPHERAL, + .ch[0] = { + .chan = LCDC_CHAN_MAINLCD, + .interface_type = RGB24, + .clock_divider = 1, + .flags = LCDC_FLAGS_DWPOL, + .lcd_size_cfg.width = 44, + .lcd_size_cfg.height = 79, + .bpp = 16, + .lcd_cfg = lcdc0_modes, + .num_cfg = ARRAY_SIZE(lcdc0_modes), + .board_cfg = { + .display_on = lcd_on, + .display_off = lcd_off, + }, + } +}; + +static struct resource lcdc0_resources[] = { + [0] = { + .name = "LCDC0", + .start = 0xfe940000, /* P4-only space */ + .end = 0xfe943fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = intcs_evt2irq(0x580), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device lcdc0_device = { + .name = "sh_mobile_lcdc_fb", + .num_resources = ARRAY_SIZE(lcdc0_resources), + .resource = lcdc0_resources, + .id = 0, + .dev = { + .platform_data = &lcdc0_info, + .coherent_dma_mask = ~0, + }, +}; + +/* MIPI-DSI */ +static struct resource mipidsi0_resources[] = { + [0] = { + .start = 0xfeab0000, + .end = 0xfeab3fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 0xfeab4000, + .end = 0xfeab7fff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct sh_mipi_dsi_info mipidsi0_info = { + .data_format = MIPI_RGB888, + .lcd_chan = &lcdc0_info.ch[0], + .vsynw_offset = 20, + .clksrc = 1, + .flags = SH_MIPI_DSI_HSABM, +}; + +static struct platform_device mipidsi0_device = { + .name = "sh-mipi-dsi", + .num_resources = ARRAY_SIZE(mipidsi0_resources), + .resource = mipidsi0_resources, + .id = 0, + .dev = { + .platform_data = &mipidsi0_info, + }, +}; + static struct platform_device *ag5evm_devices[] __initdata = { ð_device, &keysc_device, &fsi_device, &mmc_device, + &irda_device, + &lcdc0_device, + &mipidsi0_device, }; static struct map_desc ag5evm_io_desc[] __initdata = { @@ -224,6 +379,8 @@ void __init ag5evm_init_irq(void) __raw_writew(__raw_readw(PINTCR0A) | (2<<10), PINTCR0A); } +#define DSI0PHYCR 0xe615006c + static void __init ag5evm_init(void) { sh73a0_pinmux_init(); @@ -287,6 +444,26 @@ static void __init ag5evm_init(void) gpio_request(GPIO_FN_FSIAISLD, NULL); gpio_request(GPIO_FN_FSIAOSLD, NULL); + /* IrDA */ + gpio_request(GPIO_FN_PORT241_IRDA_OUT, NULL); + gpio_request(GPIO_FN_PORT242_IRDA_IN, NULL); + gpio_request(GPIO_FN_PORT243_IRDA_FIRSEL, NULL); + + /* LCD panel */ + gpio_request(GPIO_PORT217, NULL); /* RESET */ + gpio_direction_output(GPIO_PORT217, 0); + mdelay(1); + gpio_set_value(GPIO_PORT217, 1); + mdelay(100); + + /* LCD backlight controller */ + gpio_request(GPIO_PORT235, NULL); /* RESET */ + gpio_direction_output(GPIO_PORT235, 0); + lcd_backlight_reset(); + + /* MIPI-DSI clock setup */ + __raw_writel(0x2a809010, DSI0PHYCR); + #ifdef CONFIG_CACHE_L2X0 /* Shared attribute override enable, 64K*8way */ l2x0_init(__io(0xf0100000), 0x00460000, 0xc2000fff); diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 3cf0951caa2d..81d6536552a9 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -1303,7 +1303,7 @@ static void __init ap4evb_init(void) lcdc_info.clock_source = LCDC_CLK_BUS; lcdc_info.ch[0].interface_type = RGB18; - lcdc_info.ch[0].clock_divider = 2; + lcdc_info.ch[0].clock_divider = 3; lcdc_info.ch[0].flags = 0; lcdc_info.ch[0].lcd_size_cfg.width = 152; lcdc_info.ch[0].lcd_size_cfg.height = 91; diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c index 686b304a7708..ef4613b993a2 100644 --- a/arch/arm/mach-shmobile/board-g3evm.c +++ b/arch/arm/mach-shmobile/board-g3evm.c @@ -347,7 +347,6 @@ static void __init g3evm_init(void) gpio_request(GPIO_FN_IRDA_OUT, NULL); gpio_request(GPIO_FN_IRDA_IN, NULL); gpio_request(GPIO_FN_IRDA_FIRSEL, NULL); - set_irq_type(evt2irq(0x480), IRQ_TYPE_LEVEL_LOW); sh7367_add_standard_devices(); diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 7b15d21f0f68..1657eac5dde2 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -169,9 +169,8 @@ * SW1 | SW33 * | bit1 | bit2 | bit3 | bit4 * -------------+------+------+------+------- - * MMC0 OFF | OFF | ON | ON | X - * MMC1 ON | OFF | ON | X | ON - * SDHI1 OFF | ON | X | OFF | ON + * MMC0 OFF | OFF | X | ON | X (Use MMCIF) + * SDHI1 OFF | ON | X | OFF | X (Use MFD_SH_MOBILE_SDHI) * */ @@ -304,7 +303,7 @@ static struct sh_mobile_lcdc_info lcdc_info = { .lcd_cfg = mackerel_lcdc_modes, .num_cfg = ARRAY_SIZE(mackerel_lcdc_modes), .interface_type = RGB24, - .clock_divider = 2, + .clock_divider = 3, .flags = 0, .lcd_size_cfg.width = 152, .lcd_size_cfg.height = 91, diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 9aa8d68d1a9c..e9731b5a73ed 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -234,7 +234,9 @@ static int pllc2_set_rate(struct clk *clk, unsigned long rate) value = __raw_readl(PLLC2CR) & ~(0x3f << 24); - __raw_writel((value & ~0x80000000) | ((idx + 19) << 24), PLLC2CR); + __raw_writel(value | ((idx + 19) << 24), PLLC2CR); + + clk->rate = clk->freq_table[idx].frequency; return 0; } diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 720a71433be6..7e58904c1c8c 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -118,8 +118,16 @@ static unsigned long pll_recalc(struct clk *clk) { unsigned long mult = 1; - if (__raw_readl(PLLECR) & (1 << clk->enable_bit)) + if (__raw_readl(PLLECR) & (1 << clk->enable_bit)) { mult = (((__raw_readl(clk->enable_reg) >> 24) & 0x3f) + 1); + /* handle CFG bit for PLL1 and PLL2 */ + switch (clk->enable_bit) { + case 1: + case 2: + if (__raw_readl(clk->enable_reg) & (1 << 20)) + mult *= 2; + } + } return clk->parent->rate * mult; } @@ -212,7 +220,7 @@ enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2, static struct clk div4_clks[DIV4_NR] = { [DIV4_I] = DIV4(FRQCRA, 20, 0xfff, CLK_ENABLE_ON_INIT), [DIV4_ZG] = DIV4(FRQCRA, 16, 0xbff, CLK_ENABLE_ON_INIT), - [DIV4_M3] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT), + [DIV4_M3] = DIV4(FRQCRA, 12, 0xfff, CLK_ENABLE_ON_INIT), [DIV4_B] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT), [DIV4_M1] = DIV4(FRQCRA, 4, 0xfff, 0), [DIV4_M2] = DIV4(FRQCRA, 0, 0xfff, 0), @@ -255,10 +263,10 @@ static struct clk div6_clks[DIV6_NR] = { }; enum { MSTP001, - MSTP125, MSTP116, + MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100, MSTP219, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, - MSTP331, MSTP329, MSTP323, MSTP312, + MSTP331, MSTP329, MSTP325, MSTP323, MSTP312, MSTP411, MSTP410, MSTP403, MSTP_NR }; @@ -267,8 +275,14 @@ enum { MSTP001, static struct clk mstp_clks[MSTP_NR] = { [MSTP001] = MSTP(&div4_clks[DIV4_HP], SMSTPCR0, 1, 0), /* IIC2 */ + [MSTP129] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 29, 0), /* CEU1 */ + [MSTP128] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 28, 0), /* CSI2-RX1 */ + [MSTP127] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 27, 0), /* CEU0 */ + [MSTP126] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 26, 0), /* CSI2-RX0 */ [MSTP125] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 25, 0), /* TMU0 */ + [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX0 */ [MSTP116] = MSTP(&div4_clks[DIV4_HP], SMSTPCR1, 16, 0), /* IIC0 */ + [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */ [MSTP219] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 19, 0), /* SCIFA7 */ [MSTP207] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 7, 0), /* SCIFA5 */ [MSTP206] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 6, 0), /* SCIFB */ @@ -279,6 +293,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP200] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */ [MSTP331] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 31, 0), /* SCIFA6 */ [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ + [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */ [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */ [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ @@ -288,16 +303,32 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } #define CLKDEV_DEV_ID(_id, _clk) { .dev_id = _id, .clk = _clk } +#define CLKDEV_ICK_ID(_cid, _did, _clk) { .con_id = _cid, .dev_id = _did, .clk = _clk } static struct clk_lookup lookups[] = { /* main clocks */ CLKDEV_CON_ID("r_clk", &r_clk), + /* DIV6 clocks */ + CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]), + CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]), + CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), + CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), + CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), + CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), + CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), + /* MSTP32 clocks */ CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ + CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP129]), /* CEU1 */ + CLKDEV_DEV_ID("sh-mobile-csi2.1", &mstp_clks[MSTP128]), /* CSI2-RX1 */ + CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */ + CLKDEV_DEV_ID("sh-mobile-csi2.0", &mstp_clks[MSTP126]), /* CSI2-RX0 */ CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]), /* TMU00 */ CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */ + CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */ + CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */ CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */ CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */ @@ -308,6 +339,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */ CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP331]), /* SCIFA6 */ CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ + CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */ diff --git a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt index efd3687ba190..3029aba38688 100644 --- a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt +++ b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt @@ -6,13 +6,10 @@ LIST "RWT Setting" EW 0xE6020004, 0xA500 EW 0xE6030004, 0xA500 -DD 0x01001000, 0x01001000 - LIST "GPIO Setting" EB 0xE6051013, 0xA2 LIST "CPG" -ED 0xE6150080, 0x00000180 ED 0xE61500C0, 0x00000002 WAIT 1, 0xFE40009C @@ -37,6 +34,9 @@ ED 0xE615002C, 0x93000040 WAIT 1, 0xFE40009C +LIST "SUB/USBClk" +ED 0xE6150080, 0x00000180 + LIST "BSC" ED 0xFEC10000, 0x00E0001B @@ -53,7 +53,7 @@ ED 0xFE400048, 0x20C18505 ED 0xFE40004C, 0x00110209 ED 0xFE400010, 0x00000087 -WAIT 10, 0xFE40009C +WAIT 30, 0xFE40009C ED 0xFE400084, 0x0000003F EB 0xFE500000, 0x00 @@ -84,7 +84,7 @@ ED 0xE6150004, 0x80331050 WAIT 1, 0xFE40009C -ED 0xE6150354, 0x00000002 +ED 0xFE400354, 0x01AD8002 LIST "SCIF0 - Serial port for earlyprintk" EB 0xE6053098, 0x11 diff --git a/arch/arm/mach-shmobile/include/mach/head-mackerel.txt b/arch/arm/mach-shmobile/include/mach/head-mackerel.txt index efd3687ba190..3029aba38688 100644 --- a/arch/arm/mach-shmobile/include/mach/head-mackerel.txt +++ b/arch/arm/mach-shmobile/include/mach/head-mackerel.txt @@ -6,13 +6,10 @@ LIST "RWT Setting" EW 0xE6020004, 0xA500 EW 0xE6030004, 0xA500 -DD 0x01001000, 0x01001000 - LIST "GPIO Setting" EB 0xE6051013, 0xA2 LIST "CPG" -ED 0xE6150080, 0x00000180 ED 0xE61500C0, 0x00000002 WAIT 1, 0xFE40009C @@ -37,6 +34,9 @@ ED 0xE615002C, 0x93000040 WAIT 1, 0xFE40009C +LIST "SUB/USBClk" +ED 0xE6150080, 0x00000180 + LIST "BSC" ED 0xFEC10000, 0x00E0001B @@ -53,7 +53,7 @@ ED 0xFE400048, 0x20C18505 ED 0xFE40004C, 0x00110209 ED 0xFE400010, 0x00000087 -WAIT 10, 0xFE40009C +WAIT 30, 0xFE40009C ED 0xFE400084, 0x0000003F EB 0xFE500000, 0x00 @@ -84,7 +84,7 @@ ED 0xE6150004, 0x80331050 WAIT 1, 0xFE40009C -ED 0xE6150354, 0x00000002 +ED 0xFE400354, 0x01AD8002 LIST "SCIF0 - Serial port for earlyprintk" EB 0xE6053098, 0x11 diff --git a/arch/arm/mach-shmobile/include/mach/mmcif-ap4eb.h b/arch/arm/mach-shmobile/include/mach/mmcif-ap4eb.h new file mode 100644 index 000000000000..a8d02be8d2b6 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/mmcif-ap4eb.h @@ -0,0 +1,29 @@ +#ifndef MMCIF_AP4EB_H +#define MMCIF_AP4EB_H + +#define PORT185CR (void __iomem *)0xe60520b9 +#define PORT186CR (void __iomem *)0xe60520ba +#define PORT187CR (void __iomem *)0xe60520bb +#define PORT188CR (void __iomem *)0xe60520bc + +#define PORTR191_160DR (void __iomem *)0xe6056014 + +static inline void mmcif_init_progress(void) +{ + /* Initialise LEDS1-4 + * registers: PORT185CR-PORT188CR (LED1-LED4 Control) + * value: 0x10 - enable output + */ + __raw_writeb(0x10, PORT185CR); + __raw_writeb(0x10, PORT186CR); + __raw_writeb(0x10, PORT187CR); + __raw_writeb(0x10, PORT188CR); +} + +static inline void mmcif_update_progress(int n) +{ + __raw_writel((__raw_readl(PORTR191_160DR) & ~(0xf << 25)) | + (1 << (25 + n)), PORTR191_160DR); +} + +#endif /* MMCIF_AP4EB_H */ diff --git a/arch/arm/mach-shmobile/include/mach/mmcif-mackerel.h b/arch/arm/mach-shmobile/include/mach/mmcif-mackerel.h new file mode 100644 index 000000000000..4b4f6949a868 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/mmcif-mackerel.h @@ -0,0 +1,39 @@ +#ifndef MMCIF_MACKEREL_H +#define MMCIF_MACKEREL_H + +#define PORT0CR (void __iomem *)0xe6051000 +#define PORT1CR (void __iomem *)0xe6051001 +#define PORT2CR (void __iomem *)0xe6051002 +#define PORT159CR (void __iomem *)0xe605009f + +#define PORTR031_000DR (void __iomem *)0xe6055000 +#define PORTL159_128DR (void __iomem *)0xe6054010 + +static inline void mmcif_init_progress(void) +{ + /* Initialise LEDS0-3 + * registers: PORT0CR-PORT2CR,PORT159CR (LED0-LED3 Control) + * value: 0x10 - enable output + */ + __raw_writeb(0x10, PORT0CR); + __raw_writeb(0x10, PORT1CR); + __raw_writeb(0x10, PORT2CR); + __raw_writeb(0x10, PORT159CR); +} + +static inline void mmcif_update_progress(int n) +{ + unsigned a = 0, b = 0; + + if (n < 3) + a = 1 << n; + else + b = 1 << 31; + + __raw_writel((__raw_readl(PORTR031_000DR) & ~0x7) | a, + PORTR031_000DR); + __raw_writel((__raw_readl(PORTL159_128DR) & ~(1 << 31)) | b, + PORTL159_128DR); +} + +#endif /* MMCIF_MACKEREL_H */ diff --git a/arch/arm/mach-shmobile/include/mach/mmcif.h b/arch/arm/mach-shmobile/include/mach/mmcif.h new file mode 100644 index 000000000000..f4dc3279cf03 --- /dev/null +++ b/arch/arm/mach-shmobile/include/mach/mmcif.h @@ -0,0 +1,18 @@ +#ifndef MMCIF_H +#define MMCIF_H + +/************************************************** + * + * board specific settings + * + **************************************************/ + +#ifdef CONFIG_MACH_AP4EVB +#include "mach/mmcif-ap4eb.h" +#elif CONFIG_MACH_MACKEREL +#include "mach/mmcif-mackerel.h" +#else +#error "unsupported board." +#endif + +#endif /* MMCIF_H */ diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c index f78a1ead71a5..ca5f9d17b39a 100644 --- a/arch/arm/mach-shmobile/intc-sh7372.c +++ b/arch/arm/mach-shmobile/intc-sh7372.c @@ -365,6 +365,7 @@ static struct intc_desc intca_desc __initdata = { enum { UNUSED_INTCS = 0, + ENABLED_INTCS, INTCS, @@ -413,7 +414,7 @@ enum { CMT4, DSITX1_DSITX1_0, DSITX1_DSITX1_1, - /* MFIS2 */ + MFIS2_INTCS, /* Priority always enabled using ENABLED_INTCS */ CPORTS2R, /* CEC */ JPU6E, @@ -477,7 +478,7 @@ static struct intc_vect intcs_vectors[] = { INTCS_VECT(CMT4, 0x1980), INTCS_VECT(DSITX1_DSITX1_0, 0x19a0), INTCS_VECT(DSITX1_DSITX1_1, 0x19c0), - /* MFIS2 */ + INTCS_VECT(MFIS2_INTCS, 0x1a00), INTCS_VECT(CPORTS2R, 0x1a20), /* CEC */ INTCS_VECT(JPU6E, 0x1a80), @@ -543,7 +544,7 @@ static struct intc_mask_reg intcs_mask_registers[] = { { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0, CMT4, DSITX1_DSITX1_0, DSITX1_DSITX1_1, 0 } }, { 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */ - { 0, CPORTS2R, 0, 0, + { MFIS2_INTCS, CPORTS2R, 0, 0, JPU6E, 0, 0, 0 } }, { 0xffd20104, 0, 16, /* INTAMASK */ { 0, 0, 0, 0, 0, 0, 0, 0, @@ -571,7 +572,8 @@ static struct intc_prio_reg intcs_prio_registers[] = { { 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, 0 } }, { 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, DSITX1_DSITX1_0, DSITX1_DSITX1_1, 0 } }, - { 0xffd50038, 0, 16, 4, /* IPROS3 */ { 0, CPORTS2R, 0, 0 } }, + { 0xffd50038, 0, 16, 4, /* IPROS3 */ { ENABLED_INTCS, CPORTS2R, + 0, 0 } }, { 0xffd5003c, 0, 16, 4, /* IPRPS3 */ { JPU6E, 0, 0, 0 } }, }; @@ -590,6 +592,7 @@ static struct resource intcs_resources[] __initdata = { static struct intc_desc intcs_desc __initdata = { .name = "sh7372-intcs", + .force_enable = ENABLED_INTCS, .resource = intcs_resources, .num_resources = ARRAY_SIZE(intcs_resources), .hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers, diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 322d8d57cbcf..5d0e1503ece6 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -252,10 +252,11 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id) void __init sh73a0_init_irq(void) { - void __iomem *gic_base = __io(0xf0001000); + void __iomem *gic_dist_base = __io(0xf0001000); + void __iomem *gic_cpu_base = __io(0xf0000100); void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); - gic_init(0, 29, gic_base, gic_base); + gic_init(0, 29, gic_dist_base, gic_cpu_base); register_intc_controller(&intcs_desc); diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c index 18febf92f20a..98bc7edc95a6 100644 --- a/arch/arm/mach-spear3xx/clock.c +++ b/arch/arm/mach-spear3xx/clock.c @@ -13,8 +13,8 @@ #include <linux/init.h> #include <linux/kernel.h> -#include <mach/misc_regs.h> #include <plat/clock.h> +#include <mach/misc_regs.h> /* root clks */ /* 32 KHz oscillator clock */ @@ -39,18 +39,43 @@ static struct clk rtc_clk = { }; /* clock derived from 24 MHz osc clk */ +/* pll masks structure */ +static struct pll_clk_masks pll1_masks = { + .mode_mask = PLL_MODE_MASK, + .mode_shift = PLL_MODE_SHIFT, + .norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK, + .norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT, + .dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK, + .dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT, + .div_p_mask = PLL_DIV_P_MASK, + .div_p_shift = PLL_DIV_P_SHIFT, + .div_n_mask = PLL_DIV_N_MASK, + .div_n_shift = PLL_DIV_N_SHIFT, +}; + /* pll1 configuration structure */ static struct pll_clk_config pll1_config = { .mode_reg = PLL1_CTR, .cfg_reg = PLL1_FRQ, + .masks = &pll1_masks, +}; + +/* pll rate configuration table, in ascending order of rates */ +struct pll_rate_tbl pll_rtbl[] = { + {.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */ + {.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */ }; /* PLL1 clock */ static struct clk pll1_clk = { + .flags = ENABLED_ON_INIT, .pclk = &osc_24m_clk, .en_reg = PLL1_CTR, .en_reg_bit = PLL_ENABLE, - .recalc = &pll1_clk_recalc, + .calc_rate = &pll_calc_rate, + .recalc = &pll_clk_recalc, + .set_rate = &pll_clk_set_rate, + .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1}, .private_data = &pll1_config, }; @@ -76,36 +101,83 @@ static struct clk cpu_clk = { .recalc = &follow_parent, }; +/* ahb masks structure */ +static struct bus_clk_masks ahb_masks = { + .mask = PLL_HCLK_RATIO_MASK, + .shift = PLL_HCLK_RATIO_SHIFT, +}; + /* ahb configuration structure */ static struct bus_clk_config ahb_config = { .reg = CORE_CLK_CFG, - .mask = PLL_HCLK_RATIO_MASK, - .shift = PLL_HCLK_RATIO_SHIFT, + .masks = &ahb_masks, +}; + +/* ahb rate configuration table, in ascending order of rates */ +struct bus_rate_tbl bus_rtbl[] = { + {.div = 3}, /* == parent divided by 4 */ + {.div = 2}, /* == parent divided by 3 */ + {.div = 1}, /* == parent divided by 2 */ + {.div = 0}, /* == parent divided by 1 */ }; /* ahb clock */ static struct clk ahb_clk = { .flags = ALWAYS_ENABLED, .pclk = &pll1_clk, + .calc_rate = &bus_calc_rate, .recalc = &bus_clk_recalc, + .set_rate = &bus_clk_set_rate, + .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, .private_data = &ahb_config, }; -/* uart configurations */ -static struct aux_clk_config uart_config = { +/* auxiliary synthesizers masks */ +static struct aux_clk_masks aux_masks = { + .eq_sel_mask = AUX_EQ_SEL_MASK, + .eq_sel_shift = AUX_EQ_SEL_SHIFT, + .eq1_mask = AUX_EQ1_SEL, + .eq2_mask = AUX_EQ2_SEL, + .xscale_sel_mask = AUX_XSCALE_MASK, + .xscale_sel_shift = AUX_XSCALE_SHIFT, + .yscale_sel_mask = AUX_YSCALE_MASK, + .yscale_sel_shift = AUX_YSCALE_SHIFT, +}; + +/* uart synth configurations */ +static struct aux_clk_config uart_synth_config = { .synth_reg = UART_CLK_SYNT, + .masks = &aux_masks, +}; + +/* aux rate configuration table, in ascending order of rates */ +struct aux_rate_tbl aux_rtbl[] = { + /* For PLL1 = 332 MHz */ + {.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */ + {.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */ + {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */ +}; + +/* uart synth clock */ +static struct clk uart_synth_clk = { + .en_reg = UART_CLK_SYNT, + .en_reg_bit = AUX_SYNT_ENB, + .pclk = &pll1_clk, + .calc_rate = &aux_calc_rate, + .recalc = &aux_clk_recalc, + .set_rate = &aux_clk_set_rate, + .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1}, + .private_data = &uart_synth_config, }; /* uart parents */ static struct pclk_info uart_pclk_info[] = { { - .pclk = &pll1_clk, - .pclk_mask = AUX_CLK_PLL1_MASK, - .scalable = 1, + .pclk = &uart_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, }, { .pclk = &pll3_48m_clk, - .pclk_mask = AUX_CLK_PLL3_MASK, - .scalable = 0, + .pclk_val = AUX_CLK_PLL3_VAL, }, }; @@ -123,25 +195,35 @@ static struct clk uart_clk = { .en_reg_bit = UART_CLK_ENB, .pclk_sel = &uart_pclk_sel, .pclk_sel_shift = UART_CLK_SHIFT, - .recalc = &aux_clk_recalc, - .private_data = &uart_config, + .recalc = &follow_parent, }; /* firda configurations */ -static struct aux_clk_config firda_config = { +static struct aux_clk_config firda_synth_config = { .synth_reg = FIRDA_CLK_SYNT, + .masks = &aux_masks, +}; + +/* firda synth clock */ +static struct clk firda_synth_clk = { + .en_reg = FIRDA_CLK_SYNT, + .en_reg_bit = AUX_SYNT_ENB, + .pclk = &pll1_clk, + .calc_rate = &aux_calc_rate, + .recalc = &aux_clk_recalc, + .set_rate = &aux_clk_set_rate, + .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1}, + .private_data = &firda_synth_config, }; /* firda parents */ static struct pclk_info firda_pclk_info[] = { { - .pclk = &pll1_clk, - .pclk_mask = AUX_CLK_PLL1_MASK, - .scalable = 1, + .pclk = &firda_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, }, { .pclk = &pll3_48m_clk, - .pclk_mask = AUX_CLK_PLL3_MASK, - .scalable = 0, + .pclk_val = AUX_CLK_PLL3_VAL, }, }; @@ -159,73 +241,155 @@ static struct clk firda_clk = { .en_reg_bit = FIRDA_CLK_ENB, .pclk_sel = &firda_pclk_sel, .pclk_sel_shift = FIRDA_CLK_SHIFT, - .recalc = &aux_clk_recalc, - .private_data = &firda_config, + .recalc = &follow_parent, +}; + +/* gpt synthesizer masks */ +static struct gpt_clk_masks gpt_masks = { + .mscale_sel_mask = GPT_MSCALE_MASK, + .mscale_sel_shift = GPT_MSCALE_SHIFT, + .nscale_sel_mask = GPT_NSCALE_MASK, + .nscale_sel_shift = GPT_NSCALE_SHIFT, +}; + +/* gpt rate configuration table, in ascending order of rates */ +struct gpt_rate_tbl gpt_rtbl[] = { + /* For pll1 = 332 MHz */ + {.mscale = 4, .nscale = 0}, /* 41.5 MHz */ + {.mscale = 2, .nscale = 0}, /* 55.3 MHz */ + {.mscale = 1, .nscale = 0}, /* 83 MHz */ +}; + +/* gpt0 synth clk config*/ +static struct gpt_clk_config gpt0_synth_config = { + .synth_reg = PRSC1_CLK_CFG, + .masks = &gpt_masks, +}; + +/* gpt synth clock */ +static struct clk gpt0_synth_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .calc_rate = &gpt_calc_rate, + .recalc = &gpt_clk_recalc, + .set_rate = &gpt_clk_set_rate, + .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, + .private_data = &gpt0_synth_config, }; /* gpt parents */ -static struct pclk_info gpt_pclk_info[] = { +static struct pclk_info gpt0_pclk_info[] = { { - .pclk = &pll1_clk, - .pclk_mask = AUX_CLK_PLL1_MASK, - .scalable = 1, + .pclk = &gpt0_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, }, { .pclk = &pll3_48m_clk, - .pclk_mask = AUX_CLK_PLL3_MASK, - .scalable = 0, + .pclk_val = AUX_CLK_PLL3_VAL, }, }; /* gpt parent select structure */ -static struct pclk_sel gpt_pclk_sel = { - .pclk_info = gpt_pclk_info, - .pclk_count = ARRAY_SIZE(gpt_pclk_info), +static struct pclk_sel gpt0_pclk_sel = { + .pclk_info = gpt0_pclk_info, + .pclk_count = ARRAY_SIZE(gpt0_pclk_info), .pclk_sel_reg = PERIP_CLK_CFG, .pclk_sel_mask = GPT_CLK_MASK, }; -/* gpt0 configurations */ -static struct aux_clk_config gpt0_config = { - .synth_reg = PRSC1_CLK_CFG, -}; - /* gpt0 timer clock */ static struct clk gpt0_clk = { .flags = ALWAYS_ENABLED, - .pclk_sel = &gpt_pclk_sel, + .pclk_sel = &gpt0_pclk_sel, .pclk_sel_shift = GPT0_CLK_SHIFT, - .recalc = &gpt_clk_recalc, - .private_data = &gpt0_config, + .recalc = &follow_parent, }; -/* gpt1 configurations */ -static struct aux_clk_config gpt1_config = { +/* gpt1 synth clk configurations */ +static struct gpt_clk_config gpt1_synth_config = { .synth_reg = PRSC2_CLK_CFG, + .masks = &gpt_masks, +}; + +/* gpt1 synth clock */ +static struct clk gpt1_synth_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .calc_rate = &gpt_calc_rate, + .recalc = &gpt_clk_recalc, + .set_rate = &gpt_clk_set_rate, + .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, + .private_data = &gpt1_synth_config, +}; + +static struct pclk_info gpt1_pclk_info[] = { + { + .pclk = &gpt1_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, + }, { + .pclk = &pll3_48m_clk, + .pclk_val = AUX_CLK_PLL3_VAL, + }, +}; + +/* gpt parent select structure */ +static struct pclk_sel gpt1_pclk_sel = { + .pclk_info = gpt1_pclk_info, + .pclk_count = ARRAY_SIZE(gpt1_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = GPT_CLK_MASK, }; /* gpt1 timer clock */ static struct clk gpt1_clk = { .en_reg = PERIP1_CLK_ENB, .en_reg_bit = GPT1_CLK_ENB, - .pclk_sel = &gpt_pclk_sel, + .pclk_sel = &gpt1_pclk_sel, .pclk_sel_shift = GPT1_CLK_SHIFT, - .recalc = &gpt_clk_recalc, - .private_data = &gpt1_config, + .recalc = &follow_parent, }; -/* gpt2 configurations */ -static struct aux_clk_config gpt2_config = { +/* gpt2 synth clk configurations */ +static struct gpt_clk_config gpt2_synth_config = { .synth_reg = PRSC3_CLK_CFG, + .masks = &gpt_masks, +}; + +/* gpt1 synth clock */ +static struct clk gpt2_synth_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .calc_rate = &gpt_calc_rate, + .recalc = &gpt_clk_recalc, + .set_rate = &gpt_clk_set_rate, + .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, + .private_data = &gpt2_synth_config, +}; + +static struct pclk_info gpt2_pclk_info[] = { + { + .pclk = &gpt2_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, + }, { + .pclk = &pll3_48m_clk, + .pclk_val = AUX_CLK_PLL3_VAL, + }, +}; + +/* gpt parent select structure */ +static struct pclk_sel gpt2_pclk_sel = { + .pclk_info = gpt2_pclk_info, + .pclk_count = ARRAY_SIZE(gpt2_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = GPT_CLK_MASK, }; /* gpt2 timer clock */ static struct clk gpt2_clk = { .en_reg = PERIP1_CLK_ENB, .en_reg_bit = GPT2_CLK_ENB, - .pclk_sel = &gpt_pclk_sel, + .pclk_sel = &gpt2_pclk_sel, .pclk_sel_shift = GPT2_CLK_SHIFT, - .recalc = &gpt_clk_recalc, - .private_data = &gpt2_config, + .recalc = &follow_parent, }; /* clock derived from pll3 clk */ @@ -245,26 +409,27 @@ static struct clk usbd_clk = { .recalc = &follow_parent, }; -/* clcd clock */ -static struct clk clcd_clk = { - .flags = ALWAYS_ENABLED, - .pclk = &pll3_48m_clk, - .recalc = &follow_parent, +/* clock derived from ahb clk */ +/* apb masks structure */ +static struct bus_clk_masks apb_masks = { + .mask = HCLK_PCLK_RATIO_MASK, + .shift = HCLK_PCLK_RATIO_SHIFT, }; -/* clock derived from ahb clk */ /* apb configuration structure */ static struct bus_clk_config apb_config = { .reg = CORE_CLK_CFG, - .mask = HCLK_PCLK_RATIO_MASK, - .shift = HCLK_PCLK_RATIO_SHIFT, + .masks = &apb_masks, }; /* apb clock */ static struct clk apb_clk = { .flags = ALWAYS_ENABLED, .pclk = &ahb_clk, + .calc_rate = &bus_calc_rate, .recalc = &bus_clk_recalc, + .set_rate = &bus_clk_set_rate, + .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, .private_data = &apb_config, }; @@ -325,8 +490,17 @@ static struct clk adc_clk = { .recalc = &follow_parent, }; +#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) +/* emi clock */ +static struct clk emi_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &ahb_clk, + .recalc = &follow_parent, +}; +#endif + /* ssp clock */ -static struct clk ssp_clk = { +static struct clk ssp0_clk = { .pclk = &apb_clk, .en_reg = PERIP1_CLK_ENB, .en_reg_bit = SSP_CLK_ENB, @@ -343,14 +517,145 @@ static struct clk gpio_clk = { static struct clk dummy_apb_pclk; +#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \ + defined(CONFIG_MACH_SPEAR320) +/* fsmc clock */ +static struct clk fsmc_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &ahb_clk, + .recalc = &follow_parent, +}; +#endif + +/* common clocks to spear310 and spear320 */ +#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) +/* uart1 clock */ +static struct clk uart1_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* uart2 clock */ +static struct clk uart2_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; +#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */ + +/* common clocks to spear300 and spear320 */ +#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320) +/* clcd clock */ +static struct clk clcd_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll3_48m_clk, + .recalc = &follow_parent, +}; + +/* sdhci clock */ +static struct clk sdhci_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &ahb_clk, + .recalc = &follow_parent, +}; +#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */ + +/* spear300 machine specific clock structures */ +#ifdef CONFIG_MACH_SPEAR300 +/* gpio1 clock */ +static struct clk gpio1_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* keyboard clock */ +static struct clk kbd_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +#endif + +/* spear310 machine specific clock structures */ +#ifdef CONFIG_MACH_SPEAR310 +/* uart3 clock */ +static struct clk uart3_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* uart4 clock */ +static struct clk uart4_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* uart5 clock */ +static struct clk uart5_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; +#endif + +/* spear320 machine specific clock structures */ +#ifdef CONFIG_MACH_SPEAR320 +/* can0 clock */ +static struct clk can0_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* can1 clock */ +static struct clk can1_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* i2c1 clock */ +static struct clk i2c1_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &ahb_clk, + .recalc = &follow_parent, +}; + +/* ssp1 clock */ +static struct clk ssp1_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* ssp2 clock */ +static struct clk ssp2_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* pwm clock */ +static struct clk pwm_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; +#endif + /* array of all spear 3xx clock lookups */ static struct clk_lookup spear_clk_lookups[] = { - { .con_id = "apb_pclk", .clk = &dummy_apb_pclk}, + { .con_id = "apb_pclk", .clk = &dummy_apb_pclk}, /* root clks */ { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, { .con_id = "osc_24m_clk", .clk = &osc_24m_clk}, /* clock derived from 32 KHz osc clk */ - { .dev_id = "rtc", .clk = &rtc_clk}, + { .dev_id = "rtc-spear", .clk = &rtc_clk}, /* clock derived from 24 MHz osc clk */ { .con_id = "pll1_clk", .clk = &pll1_clk}, { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, @@ -358,18 +663,22 @@ static struct clk_lookup spear_clk_lookups[] = { /* clock derived from pll1 clk */ { .con_id = "cpu_clk", .clk = &cpu_clk}, { .con_id = "ahb_clk", .clk = &ahb_clk}, + { .con_id = "uart_synth_clk", .clk = &uart_synth_clk}, + { .con_id = "firda_synth_clk", .clk = &firda_synth_clk}, + { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk}, + { .con_id = "gpt1_synth_clk", .clk = &gpt1_synth_clk}, + { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk}, { .dev_id = "uart", .clk = &uart_clk}, { .dev_id = "firda", .clk = &firda_clk}, { .dev_id = "gpt0", .clk = &gpt0_clk}, { .dev_id = "gpt1", .clk = &gpt1_clk}, { .dev_id = "gpt2", .clk = &gpt2_clk}, /* clock derived from pll3 clk */ - { .dev_id = "usbh", .clk = &usbh_clk}, - { .dev_id = "usbd", .clk = &usbd_clk}, - { .dev_id = "clcd", .clk = &clcd_clk}, + { .dev_id = "designware_udc", .clk = &usbd_clk}, + { .con_id = "usbh_clk", .clk = &usbh_clk}, /* clock derived from ahb clk */ { .con_id = "apb_clk", .clk = &apb_clk}, - { .dev_id = "i2c", .clk = &i2c_clk}, + { .dev_id = "i2c_designware.0", .clk = &i2c_clk}, { .dev_id = "dma", .clk = &dma_clk}, { .dev_id = "jpeg", .clk = &jpeg_clk}, { .dev_id = "gmac", .clk = &gmac_clk}, @@ -377,8 +686,50 @@ static struct clk_lookup spear_clk_lookups[] = { { .dev_id = "c3", .clk = &c3_clk}, /* clock derived from apb clk */ { .dev_id = "adc", .clk = &adc_clk}, - { .dev_id = "ssp", .clk = &ssp_clk}, + { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk}, { .dev_id = "gpio", .clk = &gpio_clk}, +#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) + { .dev_id = "physmap-flash", .clk = &emi_clk}, +#endif +#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \ + defined(CONFIG_MACH_SPEAR320) + { .con_id = "fsmc", .clk = &fsmc_clk}, +#endif + +/* common clocks to spear310 and spear320 */ +#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) + { .dev_id = "uart1", .clk = &uart1_clk}, + { .dev_id = "uart2", .clk = &uart2_clk}, +#endif + + /* common clock to spear300 and spear320 */ +#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320) + { .dev_id = "clcd", .clk = &clcd_clk}, + { .dev_id = "sdhci", .clk = &sdhci_clk}, +#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */ + + /* spear300 machine specific clock structures */ +#ifdef CONFIG_MACH_SPEAR300 + { .dev_id = "gpio1", .clk = &gpio1_clk}, + { .dev_id = "keyboard", .clk = &kbd_clk}, +#endif + + /* spear310 machine specific clock structures */ +#ifdef CONFIG_MACH_SPEAR310 + { .dev_id = "uart3", .clk = &uart3_clk}, + { .dev_id = "uart4", .clk = &uart4_clk}, + { .dev_id = "uart5", .clk = &uart5_clk}, + +#endif + /* spear320 machine specific clock structures */ +#ifdef CONFIG_MACH_SPEAR320 + { .dev_id = "c_can_platform.0", .clk = &can0_clk}, + { .dev_id = "c_can_platform.1", .clk = &can1_clk}, + { .dev_id = "i2c_designware.1", .clk = &i2c1_clk}, + { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk}, + { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk}, + { .dev_id = "pwm", .clk = &pwm_clk}, +#endif }; void __init clk_init(void) diff --git a/arch/arm/mach-spear3xx/include/mach/entry-macro.S b/arch/arm/mach-spear3xx/include/mach/entry-macro.S index 947625d6b48d..53da4224ba3d 100644 --- a/arch/arm/mach-spear3xx/include/mach/entry-macro.S +++ b/arch/arm/mach-spear3xx/include/mach/entry-macro.S @@ -11,9 +11,8 @@ * warranty of any kind, whether express or implied. */ -#include <mach/hardware.h> -#include <mach/spear.h> #include <asm/hardware/vic.h> +#include <mach/hardware.h> .macro disable_fiq .endm diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h index af7e02c909a3..8e30636909ef 100644 --- a/arch/arm/mach-spear3xx/include/mach/generic.h +++ b/arch/arm/mach-spear3xx/include/mach/generic.h @@ -14,11 +14,11 @@ #ifndef __MACH_GENERIC_H #define __MACH_GENERIC_H -#include <asm/mach/time.h> -#include <asm/mach/map.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/amba/bus.h> +#include <asm/mach/time.h> +#include <asm/mach/map.h> #include <plat/padmux.h> /* spear3xx declarations */ @@ -33,14 +33,14 @@ /* Add spear3xx family device structure declarations here */ extern struct amba_device gpio_device; extern struct amba_device uart_device; -extern struct sys_timer spear_sys_timer; +extern struct sys_timer spear3xx_timer; /* Add spear3xx family function declarations here */ void __init clk_init(void); +void __init spear_setup_timer(void); void __init spear3xx_map_io(void); void __init spear3xx_init_irq(void); void __init spear3xx_init(void); -void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size); /* pad mux declarations */ #define PMX_FIRDA_MASK (1 << 14) @@ -129,12 +129,10 @@ extern struct pmx_dev pmx_telecom_camera; extern struct pmx_dev pmx_telecom_dac; extern struct pmx_dev pmx_telecom_i2s; extern struct pmx_dev pmx_telecom_boot_pins; -extern struct pmx_dev pmx_telecom_sdio_4bit; -extern struct pmx_dev pmx_telecom_sdio_8bit; +extern struct pmx_dev pmx_telecom_sdhci_4bit; +extern struct pmx_dev pmx_telecom_sdhci_8bit; extern struct pmx_dev pmx_gpio1; -void spear300_pmx_init(void); - /* Add spear300 machine function declarations here */ void __init spear300_init(void); @@ -154,8 +152,6 @@ extern struct pmx_dev pmx_fsmc; extern struct pmx_dev pmx_rs485_0_1; extern struct pmx_dev pmx_tdm0; -void spear310_pmx_init(void); - /* Add spear310 machine function declarations here */ void __init spear310_init(void); @@ -176,14 +172,14 @@ extern struct pmx_dev pmx_clcd; extern struct pmx_dev pmx_emi; extern struct pmx_dev pmx_fsmc; extern struct pmx_dev pmx_spp; -extern struct pmx_dev pmx_sdio; +extern struct pmx_dev pmx_sdhci; extern struct pmx_dev pmx_i2s; extern struct pmx_dev pmx_uart1; extern struct pmx_dev pmx_uart1_modem; extern struct pmx_dev pmx_uart2; extern struct pmx_dev pmx_touchscreen; extern struct pmx_dev pmx_can; -extern struct pmx_dev pmx_sdio_led; +extern struct pmx_dev pmx_sdhci_led; extern struct pmx_dev pmx_pwm0; extern struct pmx_dev pmx_pwm1; extern struct pmx_dev pmx_pwm2; @@ -195,8 +191,6 @@ extern struct pmx_dev pmx_smii0; extern struct pmx_dev pmx_smii1; extern struct pmx_dev pmx_i2c1; -void spear320_pmx_init(void); - /* Add spear320 machine function declarations here */ void __init spear320_init(void); diff --git a/arch/arm/mach-spear3xx/include/mach/hardware.h b/arch/arm/mach-spear3xx/include/mach/hardware.h index 4a86e6a3c444..4660c0d8ec0d 100644 --- a/arch/arm/mach-spear3xx/include/mach/hardware.h +++ b/arch/arm/mach-spear3xx/include/mach/hardware.h @@ -14,6 +14,9 @@ #ifndef __MACH_HARDWARE_H #define __MACH_HARDWARE_H +#include <plat/hardware.h> +#include <mach/spear.h> + /* Vitual to physical translation of statically mapped space */ #define IO_ADDRESS(x) (x | 0xF0000000) diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h index 7f940b818473..a1a7f481866d 100644 --- a/arch/arm/mach-spear3xx/include/mach/irqs.h +++ b/arch/arm/mach-spear3xx/include/mach/irqs.h @@ -69,7 +69,7 @@ #define IRQ_CLCD IRQ_GEN_RAS_3 /* IRQs sharing IRQ_INTRCOMM_RAS_ARM */ -#define IRQ_SDIO IRQ_INTRCOMM_RAS_ARM +#define IRQ_SDHCI IRQ_INTRCOMM_RAS_ARM /* GPIO pins virtual irqs */ #define SPEAR_GPIO_INT_BASE (VIRQ_START + 9) @@ -115,7 +115,7 @@ #define VIRQ_SPP (VIRQ_START + 2) /* IRQs sharing IRQ_GEN_RAS_2 */ -#define IRQ_SDIO IRQ_GEN_RAS_2 +#define IRQ_SDHCI IRQ_GEN_RAS_2 /* IRQs sharing IRQ_GEN_RAS_3 */ #define VIRQ_PLGPIO (VIRQ_START + 3) diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h index 38d767a1aba0..5bd8cd8d4852 100644 --- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h +++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h @@ -14,16 +14,16 @@ #ifndef __MACH_MISC_REGS_H #define __MACH_MISC_REGS_H -#include <mach/spear.h> +#include <mach/hardware.h> -#define MISC_BASE VA_SPEAR3XX_ICM3_MISC_REG_BASE +#define MISC_BASE IOMEM(VA_SPEAR3XX_ICM3_MISC_REG_BASE) -#define SOC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x000)) -#define DIAG_CFG_CTR ((unsigned int *)(MISC_BASE + 0x004)) -#define PLL1_CTR ((unsigned int *)(MISC_BASE + 0x008)) -#define PLL1_FRQ ((unsigned int *)(MISC_BASE + 0x00C)) -#define PLL1_MOD ((unsigned int *)(MISC_BASE + 0x010)) -#define PLL2_CTR ((unsigned int *)(MISC_BASE + 0x014)) +#define SOC_CFG_CTR (MISC_BASE + 0x000) +#define DIAG_CFG_CTR (MISC_BASE + 0x004) +#define PLL1_CTR (MISC_BASE + 0x008) +#define PLL1_FRQ (MISC_BASE + 0x00C) +#define PLL1_MOD (MISC_BASE + 0x010) +#define PLL2_CTR (MISC_BASE + 0x014) /* PLL_CTR register masks */ #define PLL_ENABLE 2 #define PLL_MODE_SHIFT 4 @@ -33,7 +33,7 @@ #define PLL_MODE_DITH_DSB 2 #define PLL_MODE_DITH_SSB 3 -#define PLL2_FRQ ((unsigned int *)(MISC_BASE + 0x018)) +#define PLL2_FRQ (MISC_BASE + 0x018) /* PLL FRQ register masks */ #define PLL_DIV_N_SHIFT 0 #define PLL_DIV_N_MASK 0xFF @@ -44,16 +44,16 @@ #define PLL_DITH_FDBK_M_SHIFT 16 #define PLL_DITH_FDBK_M_MASK 0xFFFF -#define PLL2_MOD ((unsigned int *)(MISC_BASE + 0x01C)) -#define PLL_CLK_CFG ((unsigned int *)(MISC_BASE + 0x020)) -#define CORE_CLK_CFG ((unsigned int *)(MISC_BASE + 0x024)) +#define PLL2_MOD (MISC_BASE + 0x01C) +#define PLL_CLK_CFG (MISC_BASE + 0x020) +#define CORE_CLK_CFG (MISC_BASE + 0x024) /* CORE CLK CFG register masks */ #define PLL_HCLK_RATIO_SHIFT 10 #define PLL_HCLK_RATIO_MASK 0x3 #define HCLK_PCLK_RATIO_SHIFT 8 #define HCLK_PCLK_RATIO_MASK 0x3 -#define PERIP_CLK_CFG ((unsigned int *)(MISC_BASE + 0x028)) +#define PERIP_CLK_CFG (MISC_BASE + 0x028) /* PERIP_CLK_CFG register masks */ #define UART_CLK_SHIFT 4 #define UART_CLK_MASK 0x1 @@ -63,10 +63,10 @@ #define GPT1_CLK_SHIFT 11 #define GPT2_CLK_SHIFT 12 #define GPT_CLK_MASK 0x1 -#define AUX_CLK_PLL3_MASK 0 -#define AUX_CLK_PLL1_MASK 1 +#define AUX_CLK_PLL3_VAL 0 +#define AUX_CLK_PLL1_VAL 1 -#define PERIP1_CLK_ENB ((unsigned int *)(MISC_BASE + 0x02C)) +#define PERIP1_CLK_ENB (MISC_BASE + 0x02C) /* PERIP1_CLK_ENB register masks */ #define UART_CLK_ENB 3 #define SSP_CLK_ENB 5 @@ -85,34 +85,35 @@ #define USBH_CLK_ENB 25 #define C3_CLK_ENB 31 -#define SOC_CORE_ID ((unsigned int *)(MISC_BASE + 0x030)) -#define RAS_CLK_ENB ((unsigned int *)(MISC_BASE + 0x034)) -#define PERIP1_SOF_RST ((unsigned int *)(MISC_BASE + 0x038)) +#define SOC_CORE_ID (MISC_BASE + 0x030) +#define RAS_CLK_ENB (MISC_BASE + 0x034) +#define PERIP1_SOF_RST (MISC_BASE + 0x038) /* PERIP1_SOF_RST register masks */ #define JPEG_SOF_RST 8 -#define SOC_USER_ID ((unsigned int *)(MISC_BASE + 0x03C)) -#define RAS_SOF_RST ((unsigned int *)(MISC_BASE + 0x040)) -#define PRSC1_CLK_CFG ((unsigned int *)(MISC_BASE + 0x044)) -#define PRSC2_CLK_CFG ((unsigned int *)(MISC_BASE + 0x048)) -#define PRSC3_CLK_CFG ((unsigned int *)(MISC_BASE + 0x04C)) +#define SOC_USER_ID (MISC_BASE + 0x03C) +#define RAS_SOF_RST (MISC_BASE + 0x040) +#define PRSC1_CLK_CFG (MISC_BASE + 0x044) +#define PRSC2_CLK_CFG (MISC_BASE + 0x048) +#define PRSC3_CLK_CFG (MISC_BASE + 0x04C) /* gpt synthesizer register masks */ #define GPT_MSCALE_SHIFT 0 #define GPT_MSCALE_MASK 0xFFF #define GPT_NSCALE_SHIFT 12 #define GPT_NSCALE_MASK 0xF -#define AMEM_CLK_CFG ((unsigned int *)(MISC_BASE + 0x050)) -#define EXPI_CLK_CFG ((unsigned int *)(MISC_BASE + 0x054)) -#define CLCD_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x05C)) -#define FIRDA_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x060)) -#define UART_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x064)) -#define GMAC_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x068)) -#define RAS1_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x06C)) -#define RAS2_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x070)) -#define RAS3_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x074)) -#define RAS4_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x078)) +#define AMEM_CLK_CFG (MISC_BASE + 0x050) +#define EXPI_CLK_CFG (MISC_BASE + 0x054) +#define CLCD_CLK_SYNT (MISC_BASE + 0x05C) +#define FIRDA_CLK_SYNT (MISC_BASE + 0x060) +#define UART_CLK_SYNT (MISC_BASE + 0x064) +#define GMAC_CLK_SYNT (MISC_BASE + 0x068) +#define RAS1_CLK_SYNT (MISC_BASE + 0x06C) +#define RAS2_CLK_SYNT (MISC_BASE + 0x070) +#define RAS3_CLK_SYNT (MISC_BASE + 0x074) +#define RAS4_CLK_SYNT (MISC_BASE + 0x078) /* aux clk synthesiser register masks for irda to ras4 */ +#define AUX_SYNT_ENB 31 #define AUX_EQ_SEL_SHIFT 30 #define AUX_EQ_SEL_MASK 1 #define AUX_EQ1_SEL 0 @@ -122,42 +123,42 @@ #define AUX_YSCALE_SHIFT 0 #define AUX_YSCALE_MASK 0xFFF -#define ICM1_ARB_CFG ((unsigned int *)(MISC_BASE + 0x07C)) -#define ICM2_ARB_CFG ((unsigned int *)(MISC_BASE + 0x080)) -#define ICM3_ARB_CFG ((unsigned int *)(MISC_BASE + 0x084)) -#define ICM4_ARB_CFG ((unsigned int *)(MISC_BASE + 0x088)) -#define ICM5_ARB_CFG ((unsigned int *)(MISC_BASE + 0x08C)) -#define ICM6_ARB_CFG ((unsigned int *)(MISC_BASE + 0x090)) -#define ICM7_ARB_CFG ((unsigned int *)(MISC_BASE + 0x094)) -#define ICM8_ARB_CFG ((unsigned int *)(MISC_BASE + 0x098)) -#define ICM9_ARB_CFG ((unsigned int *)(MISC_BASE + 0x09C)) -#define DMA_CHN_CFG ((unsigned int *)(MISC_BASE + 0x0A0)) -#define USB2_PHY_CFG ((unsigned int *)(MISC_BASE + 0x0A4)) -#define GMAC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0A8)) -#define EXPI_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0AC)) -#define PRC1_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C0)) -#define PRC2_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C4)) -#define PRC3_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C8)) -#define PRC4_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0CC)) -#define PRC1_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D0)) -#define PRC2_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D4)) -#define PRC3_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D8)) -#define PRC4_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0DC)) -#define PWRDOWN_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0E0)) -#define COMPSSTL_1V8_CFG ((unsigned int *)(MISC_BASE + 0x0E4)) -#define COMPSSTL_2V5_CFG ((unsigned int *)(MISC_BASE + 0x0E8)) -#define COMPCOR_3V3_CFG ((unsigned int *)(MISC_BASE + 0x0EC)) -#define SSTLPAD_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F0)) -#define BIST1_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F4)) -#define BIST2_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F8)) -#define BIST3_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0FC)) -#define BIST4_CFG_CTR ((unsigned int *)(MISC_BASE + 0x100)) -#define BIST5_CFG_CTR ((unsigned int *)(MISC_BASE + 0x104)) -#define BIST1_STS_RES ((unsigned int *)(MISC_BASE + 0x108)) -#define BIST2_STS_RES ((unsigned int *)(MISC_BASE + 0x10C)) -#define BIST3_STS_RES ((unsigned int *)(MISC_BASE + 0x110)) -#define BIST4_STS_RES ((unsigned int *)(MISC_BASE + 0x114)) -#define BIST5_STS_RES ((unsigned int *)(MISC_BASE + 0x118)) -#define SYSERR_CFG_CTR ((unsigned int *)(MISC_BASE + 0x11C)) +#define ICM1_ARB_CFG (MISC_BASE + 0x07C) +#define ICM2_ARB_CFG (MISC_BASE + 0x080) +#define ICM3_ARB_CFG (MISC_BASE + 0x084) +#define ICM4_ARB_CFG (MISC_BASE + 0x088) +#define ICM5_ARB_CFG (MISC_BASE + 0x08C) +#define ICM6_ARB_CFG (MISC_BASE + 0x090) +#define ICM7_ARB_CFG (MISC_BASE + 0x094) +#define ICM8_ARB_CFG (MISC_BASE + 0x098) +#define ICM9_ARB_CFG (MISC_BASE + 0x09C) +#define DMA_CHN_CFG (MISC_BASE + 0x0A0) +#define USB2_PHY_CFG (MISC_BASE + 0x0A4) +#define GMAC_CFG_CTR (MISC_BASE + 0x0A8) +#define EXPI_CFG_CTR (MISC_BASE + 0x0AC) +#define PRC1_LOCK_CTR (MISC_BASE + 0x0C0) +#define PRC2_LOCK_CTR (MISC_BASE + 0x0C4) +#define PRC3_LOCK_CTR (MISC_BASE + 0x0C8) +#define PRC4_LOCK_CTR (MISC_BASE + 0x0CC) +#define PRC1_IRQ_CTR (MISC_BASE + 0x0D0) +#define PRC2_IRQ_CTR (MISC_BASE + 0x0D4) +#define PRC3_IRQ_CTR (MISC_BASE + 0x0D8) +#define PRC4_IRQ_CTR (MISC_BASE + 0x0DC) +#define PWRDOWN_CFG_CTR (MISC_BASE + 0x0E0) +#define COMPSSTL_1V8_CFG (MISC_BASE + 0x0E4) +#define COMPSSTL_2V5_CFG (MISC_BASE + 0x0E8) +#define COMPCOR_3V3_CFG (MISC_BASE + 0x0EC) +#define SSTLPAD_CFG_CTR (MISC_BASE + 0x0F0) +#define BIST1_CFG_CTR (MISC_BASE + 0x0F4) +#define BIST2_CFG_CTR (MISC_BASE + 0x0F8) +#define BIST3_CFG_CTR (MISC_BASE + 0x0FC) +#define BIST4_CFG_CTR (MISC_BASE + 0x100) +#define BIST5_CFG_CTR (MISC_BASE + 0x104) +#define BIST1_STS_RES (MISC_BASE + 0x108) +#define BIST2_STS_RES (MISC_BASE + 0x10C) +#define BIST3_STS_RES (MISC_BASE + 0x110) +#define BIST4_STS_RES (MISC_BASE + 0x114) +#define BIST5_STS_RES (MISC_BASE + 0x118) +#define SYSERR_CFG_CTR (MISC_BASE + 0x11C) #endif /* __MACH_MISC_REGS_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear.h b/arch/arm/mach-spear3xx/include/mach/spear.h index dcca8568a486..63fd98356919 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear.h +++ b/arch/arm/mach-spear3xx/include/mach/spear.h @@ -14,124 +14,61 @@ #ifndef __MACH_SPEAR3XX_H #define __MACH_SPEAR3XX_H -#include <mach/hardware.h> +#include <asm/memory.h> #include <mach/spear300.h> #include <mach/spear310.h> #include <mach/spear320.h> -#define SPEAR3XX_ML_SDRAM_BASE 0x00000000 -#define SPEAR3XX_ML_SDRAM_SIZE 0x40000000 +#define SPEAR3XX_ML_SDRAM_BASE UL(0x00000000) -#define SPEAR3XX_ICM9_BASE 0xC0000000 -#define SPEAR3XX_ICM9_SIZE 0x10000000 +#define SPEAR3XX_ICM9_BASE UL(0xC0000000) /* ICM1 - Low speed connection */ -#define SPEAR3XX_ICM1_2_BASE 0xD0000000 -#define SPEAR3XX_ICM1_2_SIZE 0x10000000 - -#define SPEAR3XX_ICM1_UART_BASE 0xD0000000 +#define SPEAR3XX_ICM1_2_BASE UL(0xD0000000) +#define SPEAR3XX_ICM1_UART_BASE UL(0xD0000000) #define VA_SPEAR3XX_ICM1_UART_BASE IO_ADDRESS(SPEAR3XX_ICM1_UART_BASE) -#define SPEAR3XX_ICM1_UART_SIZE 0x00080000 - -#define SPEAR3XX_ICM1_ADC_BASE 0xD0080000 -#define SPEAR3XX_ICM1_ADC_SIZE 0x00080000 - -#define SPEAR3XX_ICM1_SSP_BASE 0xD0100000 -#define SPEAR3XX_ICM1_SSP_SIZE 0x00080000 - -#define SPEAR3XX_ICM1_I2C_BASE 0xD0180000 -#define SPEAR3XX_ICM1_I2C_SIZE 0x00080000 - -#define SPEAR3XX_ICM1_JPEG_BASE 0xD0800000 -#define SPEAR3XX_ICM1_JPEG_SIZE 0x00800000 - -#define SPEAR3XX_ICM1_IRDA_BASE 0xD1000000 -#define SPEAR3XX_ICM1_IRDA_SIZE 0x00080000 - -#define SPEAR3XX_ICM1_SRAM_BASE 0xD2800000 -#define SPEAR3XX_ICM1_SRAM_SIZE 0x05800000 +#define SPEAR3XX_ICM1_ADC_BASE UL(0xD0080000) +#define SPEAR3XX_ICM1_SSP_BASE UL(0xD0100000) +#define SPEAR3XX_ICM1_I2C_BASE UL(0xD0180000) +#define SPEAR3XX_ICM1_JPEG_BASE UL(0xD0800000) +#define SPEAR3XX_ICM1_IRDA_BASE UL(0xD1000000) +#define SPEAR3XX_ICM1_SRAM_BASE UL(0xD2800000) /* ICM2 - Application Subsystem */ -#define SPEAR3XX_ICM2_HWACCEL0_BASE 0xD8800000 -#define SPEAR3XX_ICM2_HWACCEL0_SIZE 0x00800000 - -#define SPEAR3XX_ICM2_HWACCEL1_BASE 0xD9000000 -#define SPEAR3XX_ICM2_HWACCEL1_SIZE 0x00800000 +#define SPEAR3XX_ICM2_HWACCEL0_BASE UL(0xD8800000) +#define SPEAR3XX_ICM2_HWACCEL1_BASE UL(0xD9000000) /* ICM4 - High Speed Connection */ -#define SPEAR3XX_ICM4_BASE 0xE0000000 -#define SPEAR3XX_ICM4_SIZE 0x08000000 - -#define SPEAR3XX_ICM4_MII_BASE 0xE0800000 -#define SPEAR3XX_ICM4_MII_SIZE 0x00800000 - -#define SPEAR3XX_ICM4_USBD_FIFO_BASE 0xE1000000 -#define SPEAR3XX_ICM4_USBD_FIFO_SIZE 0x00100000 - -#define SPEAR3XX_ICM4_USBD_CSR_BASE 0xE1100000 -#define SPEAR3XX_ICM4_USBD_CSR_SIZE 0x00100000 - -#define SPEAR3XX_ICM4_USBD_PLDT_BASE 0xE1200000 -#define SPEAR3XX_ICM4_USBD_PLDT_SIZE 0x00100000 - -#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE 0xE1800000 -#define SPEAR3XX_ICM4_USB_EHCI0_1_SIZE 0x00100000 - -#define SPEAR3XX_ICM4_USB_OHCI0_BASE 0xE1900000 -#define SPEAR3XX_ICM4_USB_OHCI0_SIZE 0x00100000 - -#define SPEAR3XX_ICM4_USB_OHCI1_BASE 0xE2100000 -#define SPEAR3XX_ICM4_USB_OHCI1_SIZE 0x00100000 - -#define SPEAR3XX_ICM4_USB_ARB_BASE 0xE2800000 -#define SPEAR3XX_ICM4_USB_ARB_SIZE 0x00010000 +#define SPEAR3XX_ICM4_BASE UL(0xE0000000) +#define SPEAR3XX_ICM4_MII_BASE UL(0xE0800000) +#define SPEAR3XX_ICM4_USBD_FIFO_BASE UL(0xE1000000) +#define SPEAR3XX_ICM4_USBD_CSR_BASE UL(0xE1100000) +#define SPEAR3XX_ICM4_USBD_PLDT_BASE UL(0xE1200000) +#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE UL(0xE1800000) +#define SPEAR3XX_ICM4_USB_OHCI0_BASE UL(0xE1900000) +#define SPEAR3XX_ICM4_USB_OHCI1_BASE UL(0xE2100000) +#define SPEAR3XX_ICM4_USB_ARB_BASE UL(0xE2800000) /* ML1 - Multi Layer CPU Subsystem */ -#define SPEAR3XX_ICM3_ML1_2_BASE 0xF0000000 -#define SPEAR3XX_ICM3_ML1_2_SIZE 0x0F000000 - -#define SPEAR3XX_ML1_TMR_BASE 0xF0000000 -#define SPEAR3XX_ML1_TMR_SIZE 0x00100000 - -#define SPEAR3XX_ML1_VIC_BASE 0xF1100000 +#define SPEAR3XX_ICM3_ML1_2_BASE UL(0xF0000000) +#define SPEAR3XX_ML1_TMR_BASE UL(0xF0000000) +#define SPEAR3XX_ML1_VIC_BASE UL(0xF1100000) #define VA_SPEAR3XX_ML1_VIC_BASE IO_ADDRESS(SPEAR3XX_ML1_VIC_BASE) -#define SPEAR3XX_ML1_VIC_SIZE 0x00100000 /* ICM3 - Basic Subsystem */ -#define SPEAR3XX_ICM3_SMEM_BASE 0xF8000000 -#define SPEAR3XX_ICM3_SMEM_SIZE 0x04000000 - -#define SPEAR3XX_ICM3_SMI_CTRL_BASE 0xFC000000 -#define SPEAR3XX_ICM3_SMI_CTRL_SIZE 0x00200000 - -#define SPEAR3XX_ICM3_DMA_BASE 0xFC400000 -#define SPEAR3XX_ICM3_DMA_SIZE 0x00200000 - -#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE 0xFC600000 -#define SPEAR3XX_ICM3_SDRAM_CTRL_SIZE 0x00200000 - -#define SPEAR3XX_ICM3_TMR0_BASE 0xFC800000 -#define SPEAR3XX_ICM3_TMR0_SIZE 0x00080000 - -#define SPEAR3XX_ICM3_WDT_BASE 0xFC880000 -#define SPEAR3XX_ICM3_WDT_SIZE 0x00080000 - -#define SPEAR3XX_ICM3_RTC_BASE 0xFC900000 -#define SPEAR3XX_ICM3_RTC_SIZE 0x00080000 - -#define SPEAR3XX_ICM3_GPIO_BASE 0xFC980000 -#define SPEAR3XX_ICM3_GPIO_SIZE 0x00080000 - -#define SPEAR3XX_ICM3_SYS_CTRL_BASE 0xFCA00000 +#define SPEAR3XX_ICM3_SMEM_BASE UL(0xF8000000) +#define SPEAR3XX_ICM3_SMI_CTRL_BASE UL(0xFC000000) +#define SPEAR3XX_ICM3_DMA_BASE UL(0xFC400000) +#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE UL(0xFC600000) +#define SPEAR3XX_ICM3_TMR0_BASE UL(0xFC800000) +#define SPEAR3XX_ICM3_WDT_BASE UL(0xFC880000) +#define SPEAR3XX_ICM3_RTC_BASE UL(0xFC900000) +#define SPEAR3XX_ICM3_GPIO_BASE UL(0xFC980000) +#define SPEAR3XX_ICM3_SYS_CTRL_BASE UL(0xFCA00000) #define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE IO_ADDRESS(SPEAR3XX_ICM3_SYS_CTRL_BASE) -#define SPEAR3XX_ICM3_SYS_CTRL_SIZE 0x00080000 - -#define SPEAR3XX_ICM3_MISC_REG_BASE 0xFCA80000 +#define SPEAR3XX_ICM3_MISC_REG_BASE UL(0xFCA80000) #define VA_SPEAR3XX_ICM3_MISC_REG_BASE IO_ADDRESS(SPEAR3XX_ICM3_MISC_REG_BASE) -#define SPEAR3XX_ICM3_MISC_REG_SIZE 0x00080000 - -#define SPEAR3XX_ICM3_TMR1_BASE 0xFCB00000 -#define SPEAR3XX_ICM3_TMR1_SIZE 0x00080000 +#define SPEAR3XX_ICM3_TMR1_BASE UL(0xFCB00000) /* Debug uart for linux, will be used for debug and uncompress messages */ #define SPEAR_DBG_UART_BASE SPEAR3XX_ICM1_UART_BASE diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h index ccaa76522ee2..c723515f8853 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear300.h +++ b/arch/arm/mach-spear3xx/include/mach/spear300.h @@ -17,11 +17,9 @@ #define __MACH_SPEAR300_H /* Base address of various IPs */ -#define SPEAR300_TELECOM_BASE 0x50000000 -#define SPEAR300_TELECOM_SIZE 0x10000000 +#define SPEAR300_TELECOM_BASE UL(0x50000000) /* Interrupt registers offsets and masks */ -#define SPEAR300_TELECOM_REG_SIZE 0x00010000 #define INT_ENB_MASK_REG 0x54 #define INT_STS_MASK_REG 0x58 #define IT_PERS_S_IRQ_MASK (1 << 0) @@ -36,47 +34,20 @@ #define SHIRQ_RAS1_MASK 0x1FF -#define SPEAR300_CLCD_BASE 0x60000000 -#define SPEAR300_CLCD_SIZE 0x10000000 - -#define SPEAR300_SDIO_BASE 0x70000000 -#define SPEAR300_SDIO_SIZE 0x10000000 - -#define SPEAR300_NAND_0_BASE 0x80000000 -#define SPEAR300_NAND_0_SIZE 0x04000000 - -#define SPEAR300_NAND_1_BASE 0x84000000 -#define SPEAR300_NAND_1_SIZE 0x04000000 - -#define SPEAR300_NAND_2_BASE 0x88000000 -#define SPEAR300_NAND_2_SIZE 0x04000000 - -#define SPEAR300_NAND_3_BASE 0x8c000000 -#define SPEAR300_NAND_3_SIZE 0x04000000 - -#define SPEAR300_NOR_0_BASE 0x90000000 -#define SPEAR300_NOR_0_SIZE 0x01000000 - -#define SPEAR300_NOR_1_BASE 0x91000000 -#define SPEAR300_NOR_1_SIZE 0x01000000 - -#define SPEAR300_NOR_2_BASE 0x92000000 -#define SPEAR300_NOR_2_SIZE 0x01000000 - -#define SPEAR300_NOR_3_BASE 0x93000000 -#define SPEAR300_NOR_3_SIZE 0x01000000 - -#define SPEAR300_FSMC_BASE 0x94000000 -#define SPEAR300_FSMC_SIZE 0x05000000 - -#define SPEAR300_SOC_CONFIG_BASE 0x99000000 -#define SPEAR300_SOC_CONFIG_SIZE 0x00000008 - -#define SPEAR300_KEYBOARD_BASE 0xA0000000 -#define SPEAR300_KEYBOARD_SIZE 0x09000000 - -#define SPEAR300_GPIO_BASE 0xA9000000 -#define SPEAR300_GPIO_SIZE 0x07000000 +#define SPEAR300_CLCD_BASE UL(0x60000000) +#define SPEAR300_SDHCI_BASE UL(0x70000000) +#define SPEAR300_NAND_0_BASE UL(0x80000000) +#define SPEAR300_NAND_1_BASE UL(0x84000000) +#define SPEAR300_NAND_2_BASE UL(0x88000000) +#define SPEAR300_NAND_3_BASE UL(0x8c000000) +#define SPEAR300_NOR_0_BASE UL(0x90000000) +#define SPEAR300_NOR_1_BASE UL(0x91000000) +#define SPEAR300_NOR_2_BASE UL(0x92000000) +#define SPEAR300_NOR_3_BASE UL(0x93000000) +#define SPEAR300_FSMC_BASE UL(0x94000000) +#define SPEAR300_SOC_CONFIG_BASE UL(0x99000000) +#define SPEAR300_KEYBOARD_BASE UL(0xA0000000) +#define SPEAR300_GPIO_BASE UL(0xA9000000) #endif /* __MACH_SPEAR300_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h index b27bb8af3309..1e853479b8cd 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear310.h +++ b/arch/arm/mach-spear3xx/include/mach/spear310.h @@ -16,30 +16,18 @@ #ifndef __MACH_SPEAR310_H #define __MACH_SPEAR310_H -#define SPEAR310_NAND_BASE 0x40000000 -#define SPEAR310_NAND_SIZE 0x04000000 +#define SPEAR310_NAND_BASE UL(0x40000000) +#define SPEAR310_FSMC_BASE UL(0x44000000) +#define SPEAR310_UART1_BASE UL(0xB2000000) +#define SPEAR310_UART2_BASE UL(0xB2080000) +#define SPEAR310_UART3_BASE UL(0xB2100000) +#define SPEAR310_UART4_BASE UL(0xB2180000) +#define SPEAR310_UART5_BASE UL(0xB2200000) +#define SPEAR310_HDLC_BASE UL(0xB2800000) +#define SPEAR310_RS485_0_BASE UL(0xB3000000) +#define SPEAR310_RS485_1_BASE UL(0xB3800000) +#define SPEAR310_SOC_CONFIG_BASE UL(0xB4000000) -#define SPEAR310_FSMC_BASE 0x44000000 -#define SPEAR310_FSMC_SIZE 0x01000000 - -#define SPEAR310_UART1_BASE 0xB2000000 -#define SPEAR310_UART2_BASE 0xB2080000 -#define SPEAR310_UART3_BASE 0xB2100000 -#define SPEAR310_UART4_BASE 0xB2180000 -#define SPEAR310_UART5_BASE 0xB2200000 -#define SPEAR310_UART_SIZE 0x00080000 - -#define SPEAR310_HDLC_BASE 0xB2800000 -#define SPEAR310_HDLC_SIZE 0x00800000 - -#define SPEAR310_RS485_0_BASE 0xB3000000 -#define SPEAR310_RS485_0_SIZE 0x00800000 - -#define SPEAR310_RS485_1_BASE 0xB3800000 -#define SPEAR310_RS485_1_SIZE 0x00800000 - -#define SPEAR310_SOC_CONFIG_BASE 0xB4000000 -#define SPEAR310_SOC_CONFIG_SIZE 0x00000070 /* Interrupt registers offsets and masks */ #define INT_STS_MASK_REG 0x04 #define SMII0_IRQ_MASK (1 << 0) diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h index cacf17a958cd..940f0d85d959 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear320.h +++ b/arch/arm/mach-spear3xx/include/mach/spear320.h @@ -16,54 +16,25 @@ #ifndef __MACH_SPEAR320_H #define __MACH_SPEAR320_H -#define SPEAR320_EMI_CTRL_BASE 0x40000000 -#define SPEAR320_EMI_CTRL_SIZE 0x08000000 +#define SPEAR320_EMI_CTRL_BASE UL(0x40000000) +#define SPEAR320_FSMC_BASE UL(0x4C000000) +#define SPEAR320_NAND_BASE UL(0x50000000) +#define SPEAR320_I2S_BASE UL(0x60000000) +#define SPEAR320_SDHCI_BASE UL(0x70000000) +#define SPEAR320_CLCD_BASE UL(0x90000000) +#define SPEAR320_PAR_PORT_BASE UL(0xA0000000) +#define SPEAR320_CAN0_BASE UL(0xA1000000) +#define SPEAR320_CAN1_BASE UL(0xA2000000) +#define SPEAR320_UART1_BASE UL(0xA3000000) +#define SPEAR320_UART2_BASE UL(0xA4000000) +#define SPEAR320_SSP0_BASE UL(0xA5000000) +#define SPEAR320_SSP1_BASE UL(0xA6000000) +#define SPEAR320_I2C_BASE UL(0xA7000000) +#define SPEAR320_PWM_BASE UL(0xA8000000) +#define SPEAR320_SMII0_BASE UL(0xAA000000) +#define SPEAR320_SMII1_BASE UL(0xAB000000) +#define SPEAR320_SOC_CONFIG_BASE UL(0xB3000000) -#define SPEAR320_FSMC_BASE 0x4C000000 -#define SPEAR320_FSMC_SIZE 0x01000000 - -#define SPEAR320_I2S_BASE 0x60000000 -#define SPEAR320_I2S_SIZE 0x10000000 - -#define SPEAR320_SDIO_BASE 0x70000000 -#define SPEAR320_SDIO_SIZE 0x10000000 - -#define SPEAR320_CLCD_BASE 0x90000000 -#define SPEAR320_CLCD_SIZE 0x10000000 - -#define SPEAR320_PAR_PORT_BASE 0xA0000000 -#define SPEAR320_PAR_PORT_SIZE 0x01000000 - -#define SPEAR320_CAN0_BASE 0xA1000000 -#define SPEAR320_CAN0_SIZE 0x01000000 - -#define SPEAR320_CAN1_BASE 0xA2000000 -#define SPEAR320_CAN1_SIZE 0x01000000 - -#define SPEAR320_UART1_BASE 0xA3000000 -#define SPEAR320_UART2_BASE 0xA4000000 -#define SPEAR320_UART_SIZE 0x01000000 - -#define SPEAR320_SSP0_BASE 0xA5000000 -#define SPEAR320_SSP0_SIZE 0x01000000 - -#define SPEAR320_SSP1_BASE 0xA6000000 -#define SPEAR320_SSP1_SIZE 0x01000000 - -#define SPEAR320_I2C_BASE 0xA7000000 -#define SPEAR320_I2C_SIZE 0x01000000 - -#define SPEAR320_PWM_BASE 0xA8000000 -#define SPEAR320_PWM_SIZE 0x01000000 - -#define SPEAR320_SMII0_BASE 0xAA000000 -#define SPEAR320_SMII0_SIZE 0x01000000 - -#define SPEAR320_SMII1_BASE 0xAB000000 -#define SPEAR320_SMII1_SIZE 0x01000000 - -#define SPEAR320_SOC_CONFIG_BASE 0xB4000000 -#define SPEAR320_SOC_CONFIG_SIZE 0x00000070 /* Interrupt registers offsets and masks */ #define INT_STS_MASK_REG 0x04 #define INT_CLR_MASK_REG 0x04 @@ -74,7 +45,7 @@ #define EMI_IRQ_MASK (1 << 7) #define CLCD_IRQ_MASK (1 << 8) #define SPP_IRQ_MASK (1 << 9) -#define SDIO_IRQ_MASK (1 << 10) +#define SDHCI_IRQ_MASK (1 << 10) #define CAN_U_IRQ_MASK (1 << 11) #define CAN_L_IRQ_MASK (1 << 12) #define UART1_IRQ_MASK (1 << 13) diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c index 5aa2d54ebfaa..2697e65adf86 100644 --- a/arch/arm/mach-spear3xx/spear300.c +++ b/arch/arm/mach-spear3xx/spear300.c @@ -15,9 +15,9 @@ #include <linux/amba/pl061.h> #include <linux/ptrace.h> #include <asm/irq.h> -#include <mach/generic.h> -#include <mach/spear.h> #include <plat/shirq.h> +#include <mach/generic.h> +#include <mach/hardware.h> /* pad multiplexing support */ /* muxing registers */ @@ -310,7 +310,7 @@ struct pmx_dev pmx_telecom_boot_pins = { .enb_on_reset = 1, }; -struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = { +struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = { { .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE | @@ -323,14 +323,14 @@ struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = { }, }; -struct pmx_dev pmx_telecom_sdio_4bit = { - .name = "telecom_sdio_4bit", - .modes = pmx_telecom_sdio_4bit_modes, - .mode_count = ARRAY_SIZE(pmx_telecom_sdio_4bit_modes), +struct pmx_dev pmx_telecom_sdhci_4bit = { + .name = "telecom_sdhci_4bit", + .modes = pmx_telecom_sdhci_4bit_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes), .enb_on_reset = 1, }; -struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = { +struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = { { .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE | @@ -342,10 +342,10 @@ struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = { }, }; -struct pmx_dev pmx_telecom_sdio_8bit = { - .name = "telecom_sdio_8bit", - .modes = pmx_telecom_sdio_8bit_modes, - .mode_count = ARRAY_SIZE(pmx_telecom_sdio_8bit_modes), +struct pmx_dev pmx_telecom_sdhci_8bit = { + .name = "telecom_sdhci_8bit", + .modes = pmx_telecom_sdhci_8bit_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes), .enb_on_reset = 1, }; @@ -370,26 +370,6 @@ struct pmx_driver pmx_driver = { .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff}, }; -/* Add spear300 specific devices here */ -/* arm gpio1 device registration */ -static struct pl061_platform_data gpio1_plat_data = { - .gpio_base = 8, - .irq_base = SPEAR_GPIO1_INT_BASE, -}; - -struct amba_device gpio1_device = { - .dev = { - .init_name = "gpio1", - .platform_data = &gpio1_plat_data, - }, - .res = { - .start = SPEAR300_GPIO_BASE, - .end = SPEAR300_GPIO_BASE + SPEAR300_GPIO_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {VIRQ_GPIO1, NO_IRQ}, -}; - /* spear3xx shared irq */ struct shirq_dev_config shirq_ras1_config[] = { { @@ -443,6 +423,26 @@ struct spear_shirq shirq_ras1 = { }, }; +/* Add spear300 specific devices here */ +/* arm gpio1 device registration */ +static struct pl061_platform_data gpio1_plat_data = { + .gpio_base = 8, + .irq_base = SPEAR_GPIO1_INT_BASE, +}; + +struct amba_device gpio1_device = { + .dev = { + .init_name = "gpio1", + .platform_data = &gpio1_plat_data, + }, + .res = { + .start = SPEAR300_GPIO_BASE, + .end = SPEAR300_GPIO_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {VIRQ_GPIO1, NO_IRQ}, +}; + /* spear300 routines */ void __init spear300_init(void) { @@ -452,17 +452,21 @@ void __init spear300_init(void) spear3xx_init(); /* shared irq registration */ - shirq_ras1.regs.base = - ioremap(SPEAR300_TELECOM_BASE, SPEAR300_TELECOM_REG_SIZE); + shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K); if (shirq_ras1.regs.base) { ret = spear_shirq_register(&shirq_ras1); if (ret) printk(KERN_ERR "Error registering Shared IRQ\n"); } -} -void spear300_pmx_init(void) -{ - spear_pmx_init(&pmx_driver, SPEAR300_SOC_CONFIG_BASE, - SPEAR300_SOC_CONFIG_SIZE); + /* pmx initialization */ + pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K); + if (pmx_driver.base) { + ret = pmx_register(&pmx_driver); + if (ret) + printk(KERN_ERR "padmux: registeration failed. err no" + ": %d\n", ret); + /* Free Mapping, device selection already done */ + iounmap(pmx_driver.base); + } } diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c index bb21db152a23..42d2253ef540 100644 --- a/arch/arm/mach-spear3xx/spear300_evb.c +++ b/arch/arm/mach-spear3xx/spear300_evb.c @@ -14,7 +14,7 @@ #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h> -#include <mach/spear.h> +#include <mach/hardware.h> /* padmux devices to enable */ static struct pmx_dev *pmx_devs[] = { @@ -28,7 +28,7 @@ static struct pmx_dev *pmx_devs[] = { /* spear300 specific devices */ &pmx_fsmc_2_chips, &pmx_clcd, - &pmx_telecom_sdio_4bit, + &pmx_telecom_sdhci_4bit, &pmx_gpio1, }; @@ -51,14 +51,13 @@ static void __init spear300_evb_init(void) { unsigned int i; - /* call spear300 machine init function */ - spear300_init(); - - /* padmux initialization */ + /* padmux initialization, must be done before spear300_init */ pmx_driver.mode = &photo_frame_mode; pmx_driver.devs = pmx_devs; pmx_driver.devs_count = ARRAY_SIZE(pmx_devs); - spear300_pmx_init(); + + /* call spear300 machine init function */ + spear300_init(); /* Add Platform Devices */ platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); @@ -72,6 +71,6 @@ MACHINE_START(SPEAR300, "ST-SPEAR300-EVB") .boot_params = 0x00000100, .map_io = spear3xx_map_io, .init_irq = spear3xx_init_irq, - .timer = &spear_sys_timer, + .timer = &spear3xx_timer, .init_machine = spear300_evb_init, MACHINE_END diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c index 53b41b52d7ee..5c0a67b60c2a 100644 --- a/arch/arm/mach-spear3xx/spear310.c +++ b/arch/arm/mach-spear3xx/spear310.c @@ -13,9 +13,9 @@ #include <linux/ptrace.h> #include <asm/irq.h> -#include <mach/generic.h> -#include <mach/spear.h> #include <plat/shirq.h> +#include <mach/generic.h> +#include <mach/hardware.h> /* pad multiplexing support */ /* muxing registers */ @@ -139,8 +139,6 @@ struct pmx_driver pmx_driver = { .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff}, }; -/* Add spear310 specific devices here */ - /* spear3xx shared irq */ struct shirq_dev_config shirq_ras1_config[] = { { @@ -257,6 +255,8 @@ struct spear_shirq shirq_intrcomm_ras = { }, }; +/* Add spear310 specific devices here */ + /* spear310 routines */ void __init spear310_init(void) { @@ -267,7 +267,7 @@ void __init spear310_init(void) spear3xx_init(); /* shared irq registration */ - base = ioremap(SPEAR310_SOC_CONFIG_BASE, SPEAR310_SOC_CONFIG_SIZE); + base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K); if (base) { /* shirq 1 */ shirq_ras1.regs.base = base; @@ -293,10 +293,11 @@ void __init spear310_init(void) if (ret) printk(KERN_ERR "Error registering Shared IRQ 4\n"); } -} -void spear310_pmx_init(void) -{ - spear_pmx_init(&pmx_driver, SPEAR310_SOC_CONFIG_BASE, - SPEAR310_SOC_CONFIG_SIZE); + /* pmx initialization */ + pmx_driver.base = base; + ret = pmx_register(&pmx_driver); + if (ret) + printk(KERN_ERR "padmux: registeration failed. err no: %d\n", + ret); } diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c index 7facf6643199..2d7f333bd67b 100644 --- a/arch/arm/mach-spear3xx/spear310_evb.c +++ b/arch/arm/mach-spear3xx/spear310_evb.c @@ -14,7 +14,7 @@ #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h> -#include <mach/spear.h> +#include <mach/hardware.h> /* padmux devices to enable */ static struct pmx_dev *pmx_devs[] = { @@ -58,14 +58,13 @@ static void __init spear310_evb_init(void) { unsigned int i; - /* call spear310 machine init function */ - spear310_init(); - - /* padmux initialization */ + /* padmux initialization, must be done before spear310_init */ pmx_driver.mode = NULL; pmx_driver.devs = pmx_devs; pmx_driver.devs_count = ARRAY_SIZE(pmx_devs); - spear310_pmx_init(); + + /* call spear310 machine init function */ + spear310_init(); /* Add Platform Devices */ platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); @@ -79,6 +78,6 @@ MACHINE_START(SPEAR310, "ST-SPEAR310-EVB") .boot_params = 0x00000100, .map_io = spear3xx_map_io, .init_irq = spear3xx_init_irq, - .timer = &spear_sys_timer, + .timer = &spear3xx_timer, .init_machine = spear310_evb_init, MACHINE_END diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c index 88b465284c36..741c1f414cbd 100644 --- a/arch/arm/mach-spear3xx/spear320.c +++ b/arch/arm/mach-spear3xx/spear320.c @@ -13,9 +13,9 @@ #include <linux/ptrace.h> #include <asm/irq.h> -#include <mach/generic.h> -#include <mach/spear.h> #include <plat/shirq.h> +#include <mach/generic.h> +#include <mach/hardware.h> /* pad multiplexing support */ /* muxing registers */ @@ -110,7 +110,7 @@ struct pmx_dev pmx_spp = { .enb_on_reset = 1, }; -struct pmx_dev_mode pmx_sdio_modes[] = { +struct pmx_dev_mode pmx_sdhci_modes[] = { { .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | SMALL_PRINTERS_MODE, @@ -118,10 +118,10 @@ struct pmx_dev_mode pmx_sdio_modes[] = { }, }; -struct pmx_dev pmx_sdio = { - .name = "sdio", - .modes = pmx_sdio_modes, - .mode_count = ARRAY_SIZE(pmx_sdio_modes), +struct pmx_dev pmx_sdhci = { + .name = "sdhci", + .modes = pmx_sdhci_modes, + .mode_count = ARRAY_SIZE(pmx_sdhci_modes), .enb_on_reset = 1, }; @@ -215,17 +215,17 @@ struct pmx_dev pmx_can = { .enb_on_reset = 1, }; -struct pmx_dev_mode pmx_sdio_led_modes[] = { +struct pmx_dev_mode pmx_sdhci_led_modes[] = { { .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE, .mask = PMX_SSP_CS_MASK, }, }; -struct pmx_dev pmx_sdio_led = { - .name = "sdio_led", - .modes = pmx_sdio_led_modes, - .mode_count = ARRAY_SIZE(pmx_sdio_led_modes), +struct pmx_dev pmx_sdhci_led = { + .name = "sdhci_led", + .modes = pmx_sdhci_led_modes, + .mode_count = ARRAY_SIZE(pmx_sdhci_led_modes), .enb_on_reset = 1, }; @@ -384,8 +384,6 @@ struct pmx_driver pmx_driver = { .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff}, }; -/* Add spear320 specific devices here */ - /* spear3xx shared irq */ struct shirq_dev_config shirq_ras1_config[] = { { @@ -510,6 +508,8 @@ struct spear_shirq shirq_intrcomm_ras = { }, }; +/* Add spear320 specific devices here */ + /* spear320 routines */ void __init spear320_init(void) { @@ -520,7 +520,7 @@ void __init spear320_init(void) spear3xx_init(); /* shared irq registration */ - base = ioremap(SPEAR320_SOC_CONFIG_BASE, SPEAR320_SOC_CONFIG_SIZE); + base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K); if (base) { /* shirq 1 */ shirq_ras1.regs.base = base; @@ -540,10 +540,11 @@ void __init spear320_init(void) if (ret) printk(KERN_ERR "Error registering Shared IRQ 4\n"); } -} -void spear320_pmx_init(void) -{ - spear_pmx_init(&pmx_driver, SPEAR320_SOC_CONFIG_BASE, - SPEAR320_SOC_CONFIG_SIZE); + /* pmx initialization */ + pmx_driver.base = base; + ret = pmx_register(&pmx_driver); + if (ret) + printk(KERN_ERR "padmux: registeration failed. err no: %d\n", + ret); } diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c index 62ac685a4135..8213e4b66c14 100644 --- a/arch/arm/mach-spear3xx/spear320_evb.c +++ b/arch/arm/mach-spear3xx/spear320_evb.c @@ -14,7 +14,7 @@ #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h> -#include <mach/spear.h> +#include <mach/hardware.h> /* padmux devices to enable */ static struct pmx_dev *pmx_devs[] = { @@ -26,7 +26,7 @@ static struct pmx_dev *pmx_devs[] = { /* spear320 specific devices */ &pmx_fsmc, - &pmx_sdio, + &pmx_sdhci, &pmx_i2s, &pmx_uart1, &pmx_uart2, @@ -55,14 +55,13 @@ static void __init spear320_evb_init(void) { unsigned int i; - /* call spear320 machine init function */ - spear320_init(); - - /* padmux initialization */ + /* padmux initialization, must be done before spear320_init */ pmx_driver.mode = &auto_net_mii_mode; pmx_driver.devs = pmx_devs; pmx_driver.devs_count = ARRAY_SIZE(pmx_devs); - spear320_pmx_init(); + + /* call spear320 machine init function */ + spear320_init(); /* Add Platform Devices */ platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); @@ -76,6 +75,6 @@ MACHINE_START(SPEAR320, "ST-SPEAR320-EVB") .boot_params = 0x00000100, .map_io = spear3xx_map_io, .init_irq = spear3xx_init_irq, - .timer = &spear_sys_timer, + .timer = &spear3xx_timer, .init_machine = spear320_evb_init, MACHINE_END diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c index 52f553c8c46d..d3ba8ca1bc59 100644 --- a/arch/arm/mach-spear3xx/spear3xx.c +++ b/arch/arm/mach-spear3xx/spear3xx.c @@ -19,7 +19,7 @@ #include <asm/irq.h> #include <asm/mach/arch.h> #include <mach/generic.h> -#include <mach/spear.h> +#include <mach/hardware.h> /* Add spear3xx machines common devices here */ /* gpio device registration */ @@ -35,7 +35,7 @@ struct amba_device gpio_device = { }, .res = { .start = SPEAR3XX_ICM3_GPIO_BASE, - .end = SPEAR3XX_ICM3_GPIO_BASE + SPEAR3XX_ICM3_GPIO_SIZE - 1, + .end = SPEAR3XX_ICM3_GPIO_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = {IRQ_BASIC_GPIO, NO_IRQ}, @@ -48,7 +48,7 @@ struct amba_device uart_device = { }, .res = { .start = SPEAR3XX_ICM1_UART_BASE, - .end = SPEAR3XX_ICM1_UART_BASE + SPEAR3XX_ICM1_UART_SIZE - 1, + .end = SPEAR3XX_ICM1_UART_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = {IRQ_UART, NO_IRQ}, @@ -71,22 +71,22 @@ struct map_desc spear3xx_io_desc[] __initdata = { { .virtual = VA_SPEAR3XX_ICM1_UART_BASE, .pfn = __phys_to_pfn(SPEAR3XX_ICM1_UART_BASE), - .length = SPEAR3XX_ICM1_UART_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, { .virtual = VA_SPEAR3XX_ML1_VIC_BASE, .pfn = __phys_to_pfn(SPEAR3XX_ML1_VIC_BASE), - .length = SPEAR3XX_ML1_VIC_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, { .virtual = VA_SPEAR3XX_ICM3_SYS_CTRL_BASE, .pfn = __phys_to_pfn(SPEAR3XX_ICM3_SYS_CTRL_BASE), - .length = SPEAR3XX_ICM3_SYS_CTRL_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, { .virtual = VA_SPEAR3XX_ICM3_MISC_REG_BASE, .pfn = __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE), - .length = SPEAR3XX_ICM3_MISC_REG_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, }; @@ -523,26 +523,35 @@ struct pmx_dev pmx_plgpio_45_46_49_50 = { .mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes), .enb_on_reset = 1, }; +#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */ -#endif - -/* spear padmux initialization function */ -void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size) +static void __init spear3xx_timer_init(void) { - int ret = 0; + char pclk_name[] = "pll3_48m_clk"; + struct clk *gpt_clk, *pclk; + + /* get the system timer clock */ + gpt_clk = clk_get_sys("gpt0", NULL); + if (IS_ERR(gpt_clk)) { + pr_err("%s:couldn't get clk for gpt\n", __func__); + BUG(); + } - /* pad mux initialization */ - pmx_driver->base = ioremap(base, size); - if (!pmx_driver->base) { - ret = -ENOMEM; - goto pmx_fail; + /* get the suitable parent clock for timer*/ + pclk = clk_get(NULL, pclk_name); + if (IS_ERR(pclk)) { + pr_err("%s:couldn't get %s as parent for gpt\n", + __func__, pclk_name); + BUG(); } - ret = pmx_register(pmx_driver); - iounmap(pmx_driver->base); + clk_set_parent(gpt_clk, pclk); + clk_put(gpt_clk); + clk_put(pclk); -pmx_fail: - if (ret) - printk(KERN_ERR "padmux: registration failed. err no: %d\n", - ret); + spear_setup_timer(); } + +struct sys_timer spear3xx_timer = { + .init = spear3xx_timer_init, +}; diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c index 36ff056b7321..88b748b5be80 100644 --- a/arch/arm/mach-spear6xx/clock.c +++ b/arch/arm/mach-spear6xx/clock.c @@ -13,8 +13,8 @@ #include <linux/init.h> #include <linux/kernel.h> -#include <mach/misc_regs.h> #include <plat/clock.h> +#include <mach/misc_regs.h> /* root clks */ /* 32 KHz oscillator clock */ @@ -39,18 +39,43 @@ static struct clk rtc_clk = { }; /* clock derived from 30 MHz osc clk */ +/* pll masks structure */ +static struct pll_clk_masks pll1_masks = { + .mode_mask = PLL_MODE_MASK, + .mode_shift = PLL_MODE_SHIFT, + .norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK, + .norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT, + .dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK, + .dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT, + .div_p_mask = PLL_DIV_P_MASK, + .div_p_shift = PLL_DIV_P_SHIFT, + .div_n_mask = PLL_DIV_N_MASK, + .div_n_shift = PLL_DIV_N_SHIFT, +}; + /* pll1 configuration structure */ static struct pll_clk_config pll1_config = { .mode_reg = PLL1_CTR, .cfg_reg = PLL1_FRQ, + .masks = &pll1_masks, +}; + +/* pll rate configuration table, in ascending order of rates */ +struct pll_rate_tbl pll_rtbl[] = { + {.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */ + {.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */ }; /* PLL1 clock */ static struct clk pll1_clk = { + .flags = ENABLED_ON_INIT, .pclk = &osc_30m_clk, .en_reg = PLL1_CTR, .en_reg_bit = PLL_ENABLE, - .recalc = &pll1_clk_recalc, + .calc_rate = &pll_calc_rate, + .recalc = &pll_clk_recalc, + .set_rate = &pll_clk_set_rate, + .rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1}, .private_data = &pll1_config, }; @@ -76,31 +101,83 @@ static struct clk cpu_clk = { .recalc = &follow_parent, }; +/* ahb masks structure */ +static struct bus_clk_masks ahb_masks = { + .mask = PLL_HCLK_RATIO_MASK, + .shift = PLL_HCLK_RATIO_SHIFT, +}; + /* ahb configuration structure */ static struct bus_clk_config ahb_config = { .reg = CORE_CLK_CFG, - .mask = PLL_HCLK_RATIO_MASK, - .shift = PLL_HCLK_RATIO_SHIFT, + .masks = &ahb_masks, +}; + +/* ahb rate configuration table, in ascending order of rates */ +struct bus_rate_tbl bus_rtbl[] = { + {.div = 3}, /* == parent divided by 4 */ + {.div = 2}, /* == parent divided by 3 */ + {.div = 1}, /* == parent divided by 2 */ + {.div = 0}, /* == parent divided by 1 */ }; /* ahb clock */ static struct clk ahb_clk = { .flags = ALWAYS_ENABLED, .pclk = &pll1_clk, + .calc_rate = &bus_calc_rate, .recalc = &bus_clk_recalc, + .set_rate = &bus_clk_set_rate, + .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, .private_data = &ahb_config, }; +/* auxiliary synthesizers masks */ +static struct aux_clk_masks aux_masks = { + .eq_sel_mask = AUX_EQ_SEL_MASK, + .eq_sel_shift = AUX_EQ_SEL_SHIFT, + .eq1_mask = AUX_EQ1_SEL, + .eq2_mask = AUX_EQ2_SEL, + .xscale_sel_mask = AUX_XSCALE_MASK, + .xscale_sel_shift = AUX_XSCALE_SHIFT, + .yscale_sel_mask = AUX_YSCALE_MASK, + .yscale_sel_shift = AUX_YSCALE_SHIFT, +}; + +/* uart configurations */ +static struct aux_clk_config uart_synth_config = { + .synth_reg = UART_CLK_SYNT, + .masks = &aux_masks, +}; + +/* aux rate configuration table, in ascending order of rates */ +struct aux_rate_tbl aux_rtbl[] = { + /* For PLL1 = 332 MHz */ + {.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */ + {.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */ + {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */ +}; + +/* uart synth clock */ +static struct clk uart_synth_clk = { + .en_reg = UART_CLK_SYNT, + .en_reg_bit = AUX_SYNT_ENB, + .pclk = &pll1_clk, + .calc_rate = &aux_calc_rate, + .recalc = &aux_clk_recalc, + .set_rate = &aux_clk_set_rate, + .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2}, + .private_data = &uart_synth_config, +}; + /* uart parents */ static struct pclk_info uart_pclk_info[] = { { - .pclk = &pll1_clk, - .pclk_mask = AUX_CLK_PLL1_MASK, - .scalable = 1, + .pclk = &uart_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, }, { .pclk = &pll3_48m_clk, - .pclk_mask = AUX_CLK_PLL3_MASK, - .scalable = 0, + .pclk_val = AUX_CLK_PLL3_VAL, }, }; @@ -112,19 +189,13 @@ static struct pclk_sel uart_pclk_sel = { .pclk_sel_mask = UART_CLK_MASK, }; -/* uart configurations */ -static struct aux_clk_config uart_config = { - .synth_reg = UART_CLK_SYNT, -}; - /* uart0 clock */ static struct clk uart0_clk = { .en_reg = PERIP1_CLK_ENB, .en_reg_bit = UART0_CLK_ENB, .pclk_sel = &uart_pclk_sel, .pclk_sel_shift = UART_CLK_SHIFT, - .recalc = &aux_clk_recalc, - .private_data = &uart_config, + .recalc = &follow_parent, }; /* uart1 clock */ @@ -133,25 +204,35 @@ static struct clk uart1_clk = { .en_reg_bit = UART1_CLK_ENB, .pclk_sel = &uart_pclk_sel, .pclk_sel_shift = UART_CLK_SHIFT, - .recalc = &aux_clk_recalc, - .private_data = &uart_config, + .recalc = &follow_parent, }; /* firda configurations */ -static struct aux_clk_config firda_config = { +static struct aux_clk_config firda_synth_config = { .synth_reg = FIRDA_CLK_SYNT, + .masks = &aux_masks, +}; + +/* firda synth clock */ +static struct clk firda_synth_clk = { + .en_reg = FIRDA_CLK_SYNT, + .en_reg_bit = AUX_SYNT_ENB, + .pclk = &pll1_clk, + .calc_rate = &aux_calc_rate, + .recalc = &aux_clk_recalc, + .set_rate = &aux_clk_set_rate, + .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2}, + .private_data = &firda_synth_config, }; /* firda parents */ static struct pclk_info firda_pclk_info[] = { { - .pclk = &pll1_clk, - .pclk_mask = AUX_CLK_PLL1_MASK, - .scalable = 1, + .pclk = &firda_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, }, { .pclk = &pll3_48m_clk, - .pclk_mask = AUX_CLK_PLL3_MASK, - .scalable = 0, + .pclk_val = AUX_CLK_PLL3_VAL, }, }; @@ -169,25 +250,35 @@ static struct clk firda_clk = { .en_reg_bit = FIRDA_CLK_ENB, .pclk_sel = &firda_pclk_sel, .pclk_sel_shift = FIRDA_CLK_SHIFT, - .recalc = &aux_clk_recalc, - .private_data = &firda_config, + .recalc = &follow_parent, }; /* clcd configurations */ -static struct aux_clk_config clcd_config = { +static struct aux_clk_config clcd_synth_config = { .synth_reg = CLCD_CLK_SYNT, + .masks = &aux_masks, +}; + +/* firda synth clock */ +static struct clk clcd_synth_clk = { + .en_reg = CLCD_CLK_SYNT, + .en_reg_bit = AUX_SYNT_ENB, + .pclk = &pll1_clk, + .calc_rate = &aux_calc_rate, + .recalc = &aux_clk_recalc, + .set_rate = &aux_clk_set_rate, + .rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2}, + .private_data = &clcd_synth_config, }; /* clcd parents */ static struct pclk_info clcd_pclk_info[] = { { - .pclk = &pll1_clk, - .pclk_mask = AUX_CLK_PLL1_MASK, - .scalable = 1, + .pclk = &clcd_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, }, { .pclk = &pll3_48m_clk, - .pclk_mask = AUX_CLK_PLL3_MASK, - .scalable = 0, + .pclk_val = AUX_CLK_PLL3_VAL, }, }; @@ -205,82 +296,173 @@ static struct clk clcd_clk = { .en_reg_bit = CLCD_CLK_ENB, .pclk_sel = &clcd_pclk_sel, .pclk_sel_shift = CLCD_CLK_SHIFT, - .recalc = &aux_clk_recalc, - .private_data = &clcd_config, + .recalc = &follow_parent, +}; + +/* gpt synthesizer masks */ +static struct gpt_clk_masks gpt_masks = { + .mscale_sel_mask = GPT_MSCALE_MASK, + .mscale_sel_shift = GPT_MSCALE_SHIFT, + .nscale_sel_mask = GPT_NSCALE_MASK, + .nscale_sel_shift = GPT_NSCALE_SHIFT, +}; + +/* gpt rate configuration table, in ascending order of rates */ +struct gpt_rate_tbl gpt_rtbl[] = { + /* For pll1 = 332 MHz */ + {.mscale = 4, .nscale = 0}, /* 41.5 MHz */ + {.mscale = 2, .nscale = 0}, /* 55.3 MHz */ + {.mscale = 1, .nscale = 0}, /* 83 MHz */ +}; + +/* gpt0 synth clk config*/ +static struct gpt_clk_config gpt0_synth_config = { + .synth_reg = PRSC1_CLK_CFG, + .masks = &gpt_masks, +}; + +/* gpt synth clock */ +static struct clk gpt0_synth_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .calc_rate = &gpt_calc_rate, + .recalc = &gpt_clk_recalc, + .set_rate = &gpt_clk_set_rate, + .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, + .private_data = &gpt0_synth_config, }; /* gpt parents */ -static struct pclk_info gpt_pclk_info[] = { +static struct pclk_info gpt0_pclk_info[] = { { - .pclk = &pll1_clk, - .pclk_mask = AUX_CLK_PLL1_MASK, - .scalable = 1, + .pclk = &gpt0_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, }, { .pclk = &pll3_48m_clk, - .pclk_mask = AUX_CLK_PLL3_MASK, - .scalable = 0, + .pclk_val = AUX_CLK_PLL3_VAL, }, }; /* gpt parent select structure */ -static struct pclk_sel gpt_pclk_sel = { - .pclk_info = gpt_pclk_info, - .pclk_count = ARRAY_SIZE(gpt_pclk_info), +static struct pclk_sel gpt0_pclk_sel = { + .pclk_info = gpt0_pclk_info, + .pclk_count = ARRAY_SIZE(gpt0_pclk_info), .pclk_sel_reg = PERIP_CLK_CFG, .pclk_sel_mask = GPT_CLK_MASK, }; -/* gpt0_1 configurations */ -static struct aux_clk_config gpt0_1_config = { - .synth_reg = PRSC1_CLK_CFG, -}; - /* gpt0 ARM1 subsystem timer clock */ static struct clk gpt0_clk = { .flags = ALWAYS_ENABLED, - .pclk_sel = &gpt_pclk_sel, + .pclk_sel = &gpt0_pclk_sel, .pclk_sel_shift = GPT0_CLK_SHIFT, - .recalc = &gpt_clk_recalc, - .private_data = &gpt0_1_config, + .recalc = &follow_parent, +}; + + +/* Note: gpt0 and gpt1 share same parent clocks */ +/* gpt parent select structure */ +static struct pclk_sel gpt1_pclk_sel = { + .pclk_info = gpt0_pclk_info, + .pclk_count = ARRAY_SIZE(gpt0_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = GPT_CLK_MASK, }; /* gpt1 timer clock */ static struct clk gpt1_clk = { .flags = ALWAYS_ENABLED, - .pclk_sel = &gpt_pclk_sel, + .pclk_sel = &gpt1_pclk_sel, .pclk_sel_shift = GPT1_CLK_SHIFT, - .recalc = &gpt_clk_recalc, - .private_data = &gpt0_1_config, + .recalc = &follow_parent, }; -/* gpt2 configurations */ -static struct aux_clk_config gpt2_config = { +/* gpt2 synth clk config*/ +static struct gpt_clk_config gpt2_synth_config = { .synth_reg = PRSC2_CLK_CFG, + .masks = &gpt_masks, +}; + +/* gpt synth clock */ +static struct clk gpt2_synth_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .calc_rate = &gpt_calc_rate, + .recalc = &gpt_clk_recalc, + .set_rate = &gpt_clk_set_rate, + .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, + .private_data = &gpt2_synth_config, +}; + +/* gpt parents */ +static struct pclk_info gpt2_pclk_info[] = { + { + .pclk = &gpt2_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, + }, { + .pclk = &pll3_48m_clk, + .pclk_val = AUX_CLK_PLL3_VAL, + }, +}; + +/* gpt parent select structure */ +static struct pclk_sel gpt2_pclk_sel = { + .pclk_info = gpt2_pclk_info, + .pclk_count = ARRAY_SIZE(gpt2_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = GPT_CLK_MASK, }; /* gpt2 timer clock */ static struct clk gpt2_clk = { - .en_reg = PERIP1_CLK_ENB, - .en_reg_bit = GPT2_CLK_ENB, - .pclk_sel = &gpt_pclk_sel, + .flags = ALWAYS_ENABLED, + .pclk_sel = &gpt2_pclk_sel, .pclk_sel_shift = GPT2_CLK_SHIFT, - .recalc = &gpt_clk_recalc, - .private_data = &gpt2_config, + .recalc = &follow_parent, }; -/* gpt3 configurations */ -static struct aux_clk_config gpt3_config = { +/* gpt3 synth clk config*/ +static struct gpt_clk_config gpt3_synth_config = { .synth_reg = PRSC3_CLK_CFG, + .masks = &gpt_masks, +}; + +/* gpt synth clock */ +static struct clk gpt3_synth_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .calc_rate = &gpt_calc_rate, + .recalc = &gpt_clk_recalc, + .set_rate = &gpt_clk_set_rate, + .rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2}, + .private_data = &gpt3_synth_config, +}; + +/* gpt parents */ +static struct pclk_info gpt3_pclk_info[] = { + { + .pclk = &gpt3_synth_clk, + .pclk_val = AUX_CLK_PLL1_VAL, + }, { + .pclk = &pll3_48m_clk, + .pclk_val = AUX_CLK_PLL3_VAL, + }, +}; + +/* gpt parent select structure */ +static struct pclk_sel gpt3_pclk_sel = { + .pclk_info = gpt3_pclk_info, + .pclk_count = ARRAY_SIZE(gpt3_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = GPT_CLK_MASK, }; /* gpt3 timer clock */ static struct clk gpt3_clk = { - .en_reg = PERIP1_CLK_ENB, - .en_reg_bit = GPT3_CLK_ENB, - .pclk_sel = &gpt_pclk_sel, + .flags = ALWAYS_ENABLED, + .pclk_sel = &gpt3_pclk_sel, .pclk_sel_shift = GPT3_CLK_SHIFT, - .recalc = &gpt_clk_recalc, - .private_data = &gpt3_config, + .recalc = &follow_parent, }; /* clock derived from pll3 clk */ @@ -309,18 +491,26 @@ static struct clk usbd_clk = { }; /* clock derived from ahb clk */ +/* apb masks structure */ +static struct bus_clk_masks apb_masks = { + .mask = HCLK_PCLK_RATIO_MASK, + .shift = HCLK_PCLK_RATIO_SHIFT, +}; + /* apb configuration structure */ static struct bus_clk_config apb_config = { .reg = CORE_CLK_CFG, - .mask = HCLK_PCLK_RATIO_MASK, - .shift = HCLK_PCLK_RATIO_SHIFT, + .masks = &apb_masks, }; /* apb clock */ static struct clk apb_clk = { .flags = ALWAYS_ENABLED, .pclk = &ahb_clk, + .calc_rate = &bus_calc_rate, .recalc = &bus_clk_recalc, + .set_rate = &bus_clk_set_rate, + .rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2}, .private_data = &apb_config, }; @@ -432,12 +622,12 @@ static struct clk dummy_apb_pclk; /* array of all spear 6xx clock lookups */ static struct clk_lookup spear_clk_lookups[] = { - { .con_id = "apb_pclk", .clk = &dummy_apb_pclk}, + { .con_id = "apb_pclk", .clk = &dummy_apb_pclk}, /* root clks */ { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, { .con_id = "osc_30m_clk", .clk = &osc_30m_clk}, /* clock derived from 32 KHz os clk */ - { .dev_id = "rtc", .clk = &rtc_clk}, + { .dev_id = "rtc-spear", .clk = &rtc_clk}, /* clock derived from 30 MHz os clk */ { .con_id = "pll1_clk", .clk = &pll1_clk}, { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, @@ -445,6 +635,12 @@ static struct clk_lookup spear_clk_lookups[] = { /* clock derived from pll1 clk */ { .con_id = "cpu_clk", .clk = &cpu_clk}, { .con_id = "ahb_clk", .clk = &ahb_clk}, + { .con_id = "uart_synth_clk", .clk = &uart_synth_clk}, + { .con_id = "firda_synth_clk", .clk = &firda_synth_clk}, + { .con_id = "clcd_synth_clk", .clk = &clcd_synth_clk}, + { .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk}, + { .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk}, + { .con_id = "gpt3_synth_clk", .clk = &gpt3_synth_clk}, { .dev_id = "uart0", .clk = &uart0_clk}, { .dev_id = "uart1", .clk = &uart1_clk}, { .dev_id = "firda", .clk = &firda_clk}, @@ -454,22 +650,22 @@ static struct clk_lookup spear_clk_lookups[] = { { .dev_id = "gpt2", .clk = &gpt2_clk}, { .dev_id = "gpt3", .clk = &gpt3_clk}, /* clock derived from pll3 clk */ - { .dev_id = "usbh0", .clk = &usbh0_clk}, - { .dev_id = "usbh1", .clk = &usbh1_clk}, - { .dev_id = "usbd", .clk = &usbd_clk}, + { .dev_id = "designware_udc", .clk = &usbd_clk}, + { .con_id = "usbh.0_clk", .clk = &usbh0_clk}, + { .con_id = "usbh.1_clk", .clk = &usbh1_clk}, /* clock derived from ahb clk */ { .con_id = "apb_clk", .clk = &apb_clk}, - { .dev_id = "i2c", .clk = &i2c_clk}, + { .dev_id = "i2c_designware.0", .clk = &i2c_clk}, { .dev_id = "dma", .clk = &dma_clk}, { .dev_id = "jpeg", .clk = &jpeg_clk}, { .dev_id = "gmac", .clk = &gmac_clk}, { .dev_id = "smi", .clk = &smi_clk}, - { .dev_id = "fsmc", .clk = &fsmc_clk}, + { .con_id = "fsmc", .clk = &fsmc_clk}, /* clock derived from apb clk */ { .dev_id = "adc", .clk = &adc_clk}, - { .dev_id = "ssp0", .clk = &ssp0_clk}, - { .dev_id = "ssp1", .clk = &ssp1_clk}, - { .dev_id = "ssp2", .clk = &ssp2_clk}, + { .dev_id = "ssp-pl022.0", .clk = &ssp0_clk}, + { .dev_id = "ssp-pl022.1", .clk = &ssp1_clk}, + { .dev_id = "ssp-pl022.2", .clk = &ssp2_clk}, { .dev_id = "gpio0", .clk = &gpio0_clk}, { .dev_id = "gpio1", .clk = &gpio1_clk}, { .dev_id = "gpio2", .clk = &gpio2_clk}, diff --git a/arch/arm/mach-spear6xx/include/mach/entry-macro.S b/arch/arm/mach-spear6xx/include/mach/entry-macro.S index 9eaecaeafcf0..8a0b0ed7b203 100644 --- a/arch/arm/mach-spear6xx/include/mach/entry-macro.S +++ b/arch/arm/mach-spear6xx/include/mach/entry-macro.S @@ -11,9 +11,8 @@ * warranty of any kind, whether express or implied. */ -#include <mach/hardware.h> -#include <mach/spear.h> #include <asm/hardware/vic.h> +#include <mach/hardware.h> .macro disable_fiq .endm diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h index 16205a538756..94cf4a648b57 100644 --- a/arch/arm/mach-spear6xx/include/mach/generic.h +++ b/arch/arm/mach-spear6xx/include/mach/generic.h @@ -14,11 +14,11 @@ #ifndef __MACH_GENERIC_H #define __MACH_GENERIC_H -#include <asm/mach/time.h> -#include <asm/mach/map.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/amba/bus.h> +#include <asm/mach/time.h> +#include <asm/mach/map.h> /* * Each GPT has 2 timer channels @@ -31,9 +31,10 @@ /* Add spear6xx family device structure declarations here */ extern struct amba_device gpio_device[]; extern struct amba_device uart_device[]; -extern struct sys_timer spear_sys_timer; +extern struct sys_timer spear6xx_timer; /* Add spear6xx family function declarations here */ +void __init spear_setup_timer(void); void __init spear6xx_map_io(void); void __init spear6xx_init_irq(void); void __init spear6xx_init(void); diff --git a/arch/arm/mach-spear6xx/include/mach/hardware.h b/arch/arm/mach-spear6xx/include/mach/hardware.h index 7545116deca9..0b3f96ae2848 100644 --- a/arch/arm/mach-spear6xx/include/mach/hardware.h +++ b/arch/arm/mach-spear6xx/include/mach/hardware.h @@ -14,8 +14,10 @@ #ifndef __MACH_HARDWARE_H #define __MACH_HARDWARE_H +#include <plat/hardware.h> +#include <mach/spear.h> + /* Vitual to physical translation of statically mapped space */ #define IO_ADDRESS(x) (x | 0xF0000000) #endif /* __MACH_HARDWARE_H */ - diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h index 03908036b0d0..68c20a007b0d 100644 --- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h +++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h @@ -14,16 +14,16 @@ #ifndef __MACH_MISC_REGS_H #define __MACH_MISC_REGS_H -#include <mach/spear.h> +#include <mach/hardware.h> -#define MISC_BASE VA_SPEAR6XX_ICM3_MISC_REG_BASE +#define MISC_BASE IOMEM(VA_SPEAR6XX_ICM3_MISC_REG_BASE) -#define SOC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x000)) -#define DIAG_CFG_CTR ((unsigned int *)(MISC_BASE + 0x004)) -#define PLL1_CTR ((unsigned int *)(MISC_BASE + 0x008)) -#define PLL1_FRQ ((unsigned int *)(MISC_BASE + 0x00C)) -#define PLL1_MOD ((unsigned int *)(MISC_BASE + 0x010)) -#define PLL2_CTR ((unsigned int *)(MISC_BASE + 0x014)) +#define SOC_CFG_CTR (MISC_BASE + 0x000) +#define DIAG_CFG_CTR (MISC_BASE + 0x004) +#define PLL1_CTR (MISC_BASE + 0x008) +#define PLL1_FRQ (MISC_BASE + 0x00C) +#define PLL1_MOD (MISC_BASE + 0x010) +#define PLL2_CTR (MISC_BASE + 0x014) /* PLL_CTR register masks */ #define PLL_ENABLE 2 #define PLL_MODE_SHIFT 4 @@ -33,7 +33,7 @@ #define PLL_MODE_DITH_DSB 2 #define PLL_MODE_DITH_SSB 3 -#define PLL2_FRQ ((unsigned int *)(MISC_BASE + 0x018)) +#define PLL2_FRQ (MISC_BASE + 0x018) /* PLL FRQ register masks */ #define PLL_DIV_N_SHIFT 0 #define PLL_DIV_N_MASK 0xFF @@ -44,16 +44,16 @@ #define PLL_DITH_FDBK_M_SHIFT 16 #define PLL_DITH_FDBK_M_MASK 0xFFFF -#define PLL2_MOD ((unsigned int *)(MISC_BASE + 0x01C)) -#define PLL_CLK_CFG ((unsigned int *)(MISC_BASE + 0x020)) -#define CORE_CLK_CFG ((unsigned int *)(MISC_BASE + 0x024)) +#define PLL2_MOD (MISC_BASE + 0x01C) +#define PLL_CLK_CFG (MISC_BASE + 0x020) +#define CORE_CLK_CFG (MISC_BASE + 0x024) /* CORE CLK CFG register masks */ #define PLL_HCLK_RATIO_SHIFT 10 #define PLL_HCLK_RATIO_MASK 0x3 #define HCLK_PCLK_RATIO_SHIFT 8 #define HCLK_PCLK_RATIO_MASK 0x3 -#define PERIP_CLK_CFG ((unsigned int *)(MISC_BASE + 0x028)) +#define PERIP_CLK_CFG (MISC_BASE + 0x028) /* PERIP_CLK_CFG register masks */ #define CLCD_CLK_SHIFT 2 #define CLCD_CLK_MASK 0x3 @@ -66,10 +66,10 @@ #define GPT2_CLK_SHIFT 11 #define GPT3_CLK_SHIFT 12 #define GPT_CLK_MASK 0x1 -#define AUX_CLK_PLL3_MASK 0 -#define AUX_CLK_PLL1_MASK 1 +#define AUX_CLK_PLL3_VAL 0 +#define AUX_CLK_PLL1_VAL 1 -#define PERIP1_CLK_ENB ((unsigned int *)(MISC_BASE + 0x02C)) +#define PERIP1_CLK_ENB (MISC_BASE + 0x02C) /* PERIP1_CLK_ENB register masks */ #define UART0_CLK_ENB 3 #define UART1_CLK_ENB 4 @@ -95,34 +95,35 @@ #define USBH0_CLK_ENB 25 #define USBH1_CLK_ENB 26 -#define SOC_CORE_ID ((unsigned int *)(MISC_BASE + 0x030)) -#define RAS_CLK_ENB ((unsigned int *)(MISC_BASE + 0x034)) -#define PERIP1_SOF_RST ((unsigned int *)(MISC_BASE + 0x038)) +#define SOC_CORE_ID (MISC_BASE + 0x030) +#define RAS_CLK_ENB (MISC_BASE + 0x034) +#define PERIP1_SOF_RST (MISC_BASE + 0x038) /* PERIP1_SOF_RST register masks */ #define JPEG_SOF_RST 8 -#define SOC_USER_ID ((unsigned int *)(MISC_BASE + 0x03C)) -#define RAS_SOF_RST ((unsigned int *)(MISC_BASE + 0x040)) -#define PRSC1_CLK_CFG ((unsigned int *)(MISC_BASE + 0x044)) -#define PRSC2_CLK_CFG ((unsigned int *)(MISC_BASE + 0x048)) -#define PRSC3_CLK_CFG ((unsigned int *)(MISC_BASE + 0x04C)) +#define SOC_USER_ID (MISC_BASE + 0x03C) +#define RAS_SOF_RST (MISC_BASE + 0x040) +#define PRSC1_CLK_CFG (MISC_BASE + 0x044) +#define PRSC2_CLK_CFG (MISC_BASE + 0x048) +#define PRSC3_CLK_CFG (MISC_BASE + 0x04C) /* gpt synthesizer register masks */ #define GPT_MSCALE_SHIFT 0 #define GPT_MSCALE_MASK 0xFFF #define GPT_NSCALE_SHIFT 12 #define GPT_NSCALE_MASK 0xF -#define AMEM_CLK_CFG ((unsigned int *)(MISC_BASE + 0x050)) -#define EXPI_CLK_CFG ((unsigned int *)(MISC_BASE + 0x054)) -#define CLCD_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x05C)) -#define FIRDA_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x060)) -#define UART_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x064)) -#define GMAC_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x068)) -#define RAS1_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x06C)) -#define RAS2_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x070)) -#define RAS3_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x074)) -#define RAS4_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x078)) +#define AMEM_CLK_CFG (MISC_BASE + 0x050) +#define EXPI_CLK_CFG (MISC_BASE + 0x054) +#define CLCD_CLK_SYNT (MISC_BASE + 0x05C) +#define FIRDA_CLK_SYNT (MISC_BASE + 0x060) +#define UART_CLK_SYNT (MISC_BASE + 0x064) +#define GMAC_CLK_SYNT (MISC_BASE + 0x068) +#define RAS1_CLK_SYNT (MISC_BASE + 0x06C) +#define RAS2_CLK_SYNT (MISC_BASE + 0x070) +#define RAS3_CLK_SYNT (MISC_BASE + 0x074) +#define RAS4_CLK_SYNT (MISC_BASE + 0x078) /* aux clk synthesiser register masks for irda to ras4 */ +#define AUX_SYNT_ENB 31 #define AUX_EQ_SEL_SHIFT 30 #define AUX_EQ_SEL_MASK 1 #define AUX_EQ1_SEL 0 @@ -132,42 +133,42 @@ #define AUX_YSCALE_SHIFT 0 #define AUX_YSCALE_MASK 0xFFF -#define ICM1_ARB_CFG ((unsigned int *)(MISC_BASE + 0x07C)) -#define ICM2_ARB_CFG ((unsigned int *)(MISC_BASE + 0x080)) -#define ICM3_ARB_CFG ((unsigned int *)(MISC_BASE + 0x084)) -#define ICM4_ARB_CFG ((unsigned int *)(MISC_BASE + 0x088)) -#define ICM5_ARB_CFG ((unsigned int *)(MISC_BASE + 0x08C)) -#define ICM6_ARB_CFG ((unsigned int *)(MISC_BASE + 0x090)) -#define ICM7_ARB_CFG ((unsigned int *)(MISC_BASE + 0x094)) -#define ICM8_ARB_CFG ((unsigned int *)(MISC_BASE + 0x098)) -#define ICM9_ARB_CFG ((unsigned int *)(MISC_BASE + 0x09C)) -#define DMA_CHN_CFG ((unsigned int *)(MISC_BASE + 0x0A0)) -#define USB2_PHY_CFG ((unsigned int *)(MISC_BASE + 0x0A4)) -#define GMAC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0A8)) -#define EXPI_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0AC)) -#define PRC1_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C0)) -#define PRC2_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C4)) -#define PRC3_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C8)) -#define PRC4_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0CC)) -#define PRC1_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D0)) -#define PRC2_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D4)) -#define PRC3_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D8)) -#define PRC4_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0DC)) -#define PWRDOWN_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0E0)) -#define COMPSSTL_1V8_CFG ((unsigned int *)(MISC_BASE + 0x0E4)) -#define COMPSSTL_2V5_CFG ((unsigned int *)(MISC_BASE + 0x0E8)) -#define COMPCOR_3V3_CFG ((unsigned int *)(MISC_BASE + 0x0EC)) -#define SSTLPAD_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F0)) -#define BIST1_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F4)) -#define BIST2_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F8)) -#define BIST3_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0FC)) -#define BIST4_CFG_CTR ((unsigned int *)(MISC_BASE + 0x100)) -#define BIST5_CFG_CTR ((unsigned int *)(MISC_BASE + 0x104)) -#define BIST1_STS_RES ((unsigned int *)(MISC_BASE + 0x108)) -#define BIST2_STS_RES ((unsigned int *)(MISC_BASE + 0x10C)) -#define BIST3_STS_RES ((unsigned int *)(MISC_BASE + 0x110)) -#define BIST4_STS_RES ((unsigned int *)(MISC_BASE + 0x114)) -#define BIST5_STS_RES ((unsigned int *)(MISC_BASE + 0x118)) -#define SYSERR_CFG_CTR ((unsigned int *)(MISC_BASE + 0x11C)) +#define ICM1_ARB_CFG (MISC_BASE + 0x07C) +#define ICM2_ARB_CFG (MISC_BASE + 0x080) +#define ICM3_ARB_CFG (MISC_BASE + 0x084) +#define ICM4_ARB_CFG (MISC_BASE + 0x088) +#define ICM5_ARB_CFG (MISC_BASE + 0x08C) +#define ICM6_ARB_CFG (MISC_BASE + 0x090) +#define ICM7_ARB_CFG (MISC_BASE + 0x094) +#define ICM8_ARB_CFG (MISC_BASE + 0x098) +#define ICM9_ARB_CFG (MISC_BASE + 0x09C) +#define DMA_CHN_CFG (MISC_BASE + 0x0A0) +#define USB2_PHY_CFG (MISC_BASE + 0x0A4) +#define GMAC_CFG_CTR (MISC_BASE + 0x0A8) +#define EXPI_CFG_CTR (MISC_BASE + 0x0AC) +#define PRC1_LOCK_CTR (MISC_BASE + 0x0C0) +#define PRC2_LOCK_CTR (MISC_BASE + 0x0C4) +#define PRC3_LOCK_CTR (MISC_BASE + 0x0C8) +#define PRC4_LOCK_CTR (MISC_BASE + 0x0CC) +#define PRC1_IRQ_CTR (MISC_BASE + 0x0D0) +#define PRC2_IRQ_CTR (MISC_BASE + 0x0D4) +#define PRC3_IRQ_CTR (MISC_BASE + 0x0D8) +#define PRC4_IRQ_CTR (MISC_BASE + 0x0DC) +#define PWRDOWN_CFG_CTR (MISC_BASE + 0x0E0) +#define COMPSSTL_1V8_CFG (MISC_BASE + 0x0E4) +#define COMPSSTL_2V5_CFG (MISC_BASE + 0x0E8) +#define COMPCOR_3V3_CFG (MISC_BASE + 0x0EC) +#define SSTLPAD_CFG_CTR (MISC_BASE + 0x0F0) +#define BIST1_CFG_CTR (MISC_BASE + 0x0F4) +#define BIST2_CFG_CTR (MISC_BASE + 0x0F8) +#define BIST3_CFG_CTR (MISC_BASE + 0x0FC) +#define BIST4_CFG_CTR (MISC_BASE + 0x100) +#define BIST5_CFG_CTR (MISC_BASE + 0x104) +#define BIST1_STS_RES (MISC_BASE + 0x108) +#define BIST2_STS_RES (MISC_BASE + 0x10C) +#define BIST3_STS_RES (MISC_BASE + 0x110) +#define BIST4_STS_RES (MISC_BASE + 0x114) +#define BIST5_STS_RES (MISC_BASE + 0x118) +#define SYSERR_CFG_CTR (MISC_BASE + 0x11C) #endif /* __MACH_MISC_REGS_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/spear.h b/arch/arm/mach-spear6xx/include/mach/spear.h index a835f5b6b182..7fd621532def 100644 --- a/arch/arm/mach-spear6xx/include/mach/spear.h +++ b/arch/arm/mach-spear6xx/include/mach/spear.h @@ -14,153 +14,70 @@ #ifndef __MACH_SPEAR6XX_H #define __MACH_SPEAR6XX_H -#include <mach/hardware.h> +#include <asm/memory.h> #include <mach/spear600.h> -#define SPEAR6XX_ML_SDRAM_BASE 0x00000000 -#define SPEAR6XX_ML_SDRAM_SIZE 0x40000000 - +#define SPEAR6XX_ML_SDRAM_BASE UL(0x00000000) /* ICM1 - Low speed connection */ -#define SPEAR6XX_ICM1_BASE 0xD0000000 -#define SPEAR6XX_ICM1_SIZE 0x08000000 +#define SPEAR6XX_ICM1_BASE UL(0xD0000000) -#define SPEAR6XX_ICM1_UART0_BASE 0xD0000000 +#define SPEAR6XX_ICM1_UART0_BASE UL(0xD0000000) #define VA_SPEAR6XX_ICM1_UART0_BASE IO_ADDRESS(SPEAR6XX_ICM1_UART0_BASE) -#define SPEAR6XX_ICM1_UART0_SIZE 0x00080000 - -#define SPEAR6XX_ICM1_UART1_BASE 0xD0080000 -#define SPEAR6XX_ICM1_UART1_SIZE 0x00080000 - -#define SPEAR6XX_ICM1_SSP0_BASE 0xD0100000 -#define SPEAR6XX_ICM1_SSP0_SIZE 0x00080000 - -#define SPEAR6XX_ICM1_SSP1_BASE 0xD0180000 -#define SPEAR6XX_ICM1_SSP1_SIZE 0x00080000 - -#define SPEAR6XX_ICM1_I2C_BASE 0xD0200000 -#define SPEAR6XX_ICM1_I2C_SIZE 0x00080000 -#define SPEAR6XX_ICM1_JPEG_BASE 0xD0800000 -#define SPEAR6XX_ICM1_JPEG_SIZE 0x00800000 - -#define SPEAR6XX_ICM1_IRDA_BASE 0xD1000000 -#define SPEAR6XX_ICM1_IRDA_SIZE 0x00800000 - -#define SPEAR6XX_ICM1_FSMC_BASE 0xD1800000 -#define SPEAR6XX_ICM1_FSMC_SIZE 0x00800000 - -#define SPEAR6XX_ICM1_NAND_BASE 0xD2000000 -#define SPEAR6XX_ICM1_NAND_SIZE 0x00800000 - -#define SPEAR6XX_ICM1_SRAM_BASE 0xD2800000 -#define SPEAR6XX_ICM1_SRAM_SIZE 0x00800000 +#define SPEAR6XX_ICM1_UART1_BASE UL(0xD0080000) +#define SPEAR6XX_ICM1_SSP0_BASE UL(0xD0100000) +#define SPEAR6XX_ICM1_SSP1_BASE UL(0xD0180000) +#define SPEAR6XX_ICM1_I2C_BASE UL(0xD0200000) +#define SPEAR6XX_ICM1_JPEG_BASE UL(0xD0800000) +#define SPEAR6XX_ICM1_IRDA_BASE UL(0xD1000000) +#define SPEAR6XX_ICM1_FSMC_BASE UL(0xD1800000) +#define SPEAR6XX_ICM1_NAND_BASE UL(0xD2000000) +#define SPEAR6XX_ICM1_SRAM_BASE UL(0xD2800000) /* ICM2 - Application Subsystem */ -#define SPEAR6XX_ICM2_BASE 0xD8000000 -#define SPEAR6XX_ICM2_SIZE 0x08000000 - -#define SPEAR6XX_ICM2_TMR0_BASE 0xD8000000 -#define SPEAR6XX_ICM2_TMR0_SIZE 0x00080000 - -#define SPEAR6XX_ICM2_TMR1_BASE 0xD8080000 -#define SPEAR6XX_ICM2_TMR1_SIZE 0x00080000 - -#define SPEAR6XX_ICM2_GPIO_BASE 0xD8100000 -#define SPEAR6XX_ICM2_GPIO_SIZE 0x00080000 - -#define SPEAR6XX_ICM2_SPI2_BASE 0xD8180000 -#define SPEAR6XX_ICM2_SPI2_SIZE 0x00080000 - -#define SPEAR6XX_ICM2_ADC_BASE 0xD8200000 -#define SPEAR6XX_ICM2_ADC_SIZE 0x00080000 +#define SPEAR6XX_ICM2_BASE UL(0xD8000000) +#define SPEAR6XX_ICM2_TMR0_BASE UL(0xD8000000) +#define SPEAR6XX_ICM2_TMR1_BASE UL(0xD8080000) +#define SPEAR6XX_ICM2_GPIO_BASE UL(0xD8100000) +#define SPEAR6XX_ICM2_SSP2_BASE UL(0xD8180000) +#define SPEAR6XX_ICM2_ADC_BASE UL(0xD8200000) /* ML-1, 2 - Multi Layer CPU Subsystem */ -#define SPEAR6XX_ML_CPU_BASE 0xF0000000 -#define SPEAR6XX_ML_CPU_SIZE 0x08000000 - -#define SPEAR6XX_CPU_TMR_BASE 0xF0000000 -#define SPEAR6XX_CPU_TMR_SIZE 0x00100000 - -#define SPEAR6XX_CPU_GPIO_BASE 0xF0100000 -#define SPEAR6XX_CPU_GPIO_SIZE 0x00100000 - -#define SPEAR6XX_CPU_VIC_SEC_BASE 0xF1000000 +#define SPEAR6XX_ML_CPU_BASE UL(0xF0000000) +#define SPEAR6XX_CPU_TMR_BASE UL(0xF0000000) +#define SPEAR6XX_CPU_GPIO_BASE UL(0xF0100000) +#define SPEAR6XX_CPU_VIC_SEC_BASE UL(0xF1000000) #define VA_SPEAR6XX_CPU_VIC_SEC_BASE IO_ADDRESS(SPEAR6XX_CPU_VIC_SEC_BASE) -#define SPEAR6XX_CPU_VIC_SEC_SIZE 0x00100000 - -#define SPEAR6XX_CPU_VIC_PRI_BASE 0xF1100000 +#define SPEAR6XX_CPU_VIC_PRI_BASE UL(0xF1100000) #define VA_SPEAR6XX_CPU_VIC_PRI_BASE IO_ADDRESS(SPEAR6XX_CPU_VIC_PRI_BASE) -#define SPEAR6XX_CPU_VIC_PRI_SIZE 0x00100000 /* ICM3 - Basic Subsystem */ -#define SPEAR6XX_ICM3_BASE 0xF8000000 -#define SPEAR6XX_ICM3_SIZE 0x08000000 - -#define SPEAR6XX_ICM3_SMEM_BASE 0xF8000000 -#define SPEAR6XX_ICM3_SMEM_SIZE 0x04000000 - -#define SPEAR6XX_ICM3_SMI_CTRL_BASE 0xFC000000 -#define SPEAR6XX_ICM3_SMI_CTRL_SIZE 0x00200000 - -#define SPEAR6XX_ICM3_CLCD_BASE 0xFC200000 -#define SPEAR6XX_ICM3_CLCD_SIZE 0x00200000 - -#define SPEAR6XX_ICM3_DMA_BASE 0xFC400000 -#define SPEAR6XX_ICM3_DMA_SIZE 0x00200000 - -#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE 0xFC600000 -#define SPEAR6XX_ICM3_SDRAM_CTRL_SIZE 0x00200000 - -#define SPEAR6XX_ICM3_TMR_BASE 0xFC800000 -#define SPEAR6XX_ICM3_TMR_SIZE 0x00080000 - -#define SPEAR6XX_ICM3_WDT_BASE 0xFC880000 -#define SPEAR6XX_ICM3_WDT_SIZE 0x00080000 - -#define SPEAR6XX_ICM3_RTC_BASE 0xFC900000 -#define SPEAR6XX_ICM3_RTC_SIZE 0x00080000 - -#define SPEAR6XX_ICM3_GPIO_BASE 0xFC980000 -#define SPEAR6XX_ICM3_GPIO_SIZE 0x00080000 - -#define SPEAR6XX_ICM3_SYS_CTRL_BASE 0xFCA00000 +#define SPEAR6XX_ICM3_BASE UL(0xF8000000) +#define SPEAR6XX_ICM3_SMEM_BASE UL(0xF8000000) +#define SPEAR6XX_ICM3_SMI_CTRL_BASE UL(0xFC000000) +#define SPEAR6XX_ICM3_CLCD_BASE UL(0xFC200000) +#define SPEAR6XX_ICM3_DMA_BASE UL(0xFC400000) +#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE UL(0xFC600000) +#define SPEAR6XX_ICM3_TMR_BASE UL(0xFC800000) +#define SPEAR6XX_ICM3_WDT_BASE UL(0xFC880000) +#define SPEAR6XX_ICM3_RTC_BASE UL(0xFC900000) +#define SPEAR6XX_ICM3_GPIO_BASE UL(0xFC980000) +#define SPEAR6XX_ICM3_SYS_CTRL_BASE UL(0xFCA00000) #define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE IO_ADDRESS(SPEAR6XX_ICM3_SYS_CTRL_BASE) -#define SPEAR6XX_ICM3_SYS_CTRL_SIZE 0x00080000 - -#define SPEAR6XX_ICM3_MISC_REG_BASE 0xFCA80000 +#define SPEAR6XX_ICM3_MISC_REG_BASE UL(0xFCA80000) #define VA_SPEAR6XX_ICM3_MISC_REG_BASE IO_ADDRESS(SPEAR6XX_ICM3_MISC_REG_BASE) -#define SPEAR6XX_ICM3_MISC_REG_SIZE 0x00080000 /* ICM4 - High Speed Connection */ -#define SPEAR6XX_ICM4_BASE 0xE0000000 -#define SPEAR6XX_ICM4_SIZE 0x08000000 - -#define SPEAR6XX_ICM4_GMAC_BASE 0xE0800000 -#define SPEAR6XX_ICM4_GMAC_SIZE 0x00800000 - -#define SPEAR6XX_ICM4_USBD_FIFO_BASE 0xE1000000 -#define SPEAR6XX_ICM4_USBD_FIFO_SIZE 0x00100000 - -#define SPEAR6XX_ICM4_USBD_CSR_BASE 0xE1100000 -#define SPEAR6XX_ICM4_USBD_CSR_SIZE 0x00100000 - -#define SPEAR6XX_ICM4_USBD_PLDT_BASE 0xE1200000 -#define SPEAR6XX_ICM4_USBD_PLDT_SIZE 0x00100000 - -#define SPEAR6XX_ICM4_USB_EHCI0_BASE 0xE1800000 -#define SPEAR6XX_ICM4_USB_EHCI0_SIZE 0x00100000 - -#define SPEAR6XX_ICM4_USB_OHCI0_BASE 0xE1900000 -#define SPEAR6XX_ICM4_USB_OHCI0_SIZE 0x00100000 - -#define SPEAR6XX_ICM4_USB_EHCI1_BASE 0xE2000000 -#define SPEAR6XX_ICM4_USB_EHCI1_SIZE 0x00100000 - -#define SPEAR6XX_ICM4_USB_OHCI1_BASE 0xE2100000 -#define SPEAR6XX_ICM4_USB_OHCI1_SIZE 0x00100000 - -#define SPEAR6XX_ICM4_USB_ARB_BASE 0xE2800000 -#define SPEAR6XX_ICM4_USB_ARB_SIZE 0x00010000 +#define SPEAR6XX_ICM4_BASE UL(0xE0000000) +#define SPEAR6XX_ICM4_GMAC_BASE UL(0xE0800000) +#define SPEAR6XX_ICM4_USBD_FIFO_BASE UL(0xE1000000) +#define SPEAR6XX_ICM4_USBD_CSR_BASE UL(0xE1100000) +#define SPEAR6XX_ICM4_USBD_PLDT_BASE UL(0xE1200000) +#define SPEAR6XX_ICM4_USB_EHCI0_BASE UL(0xE1800000) +#define SPEAR6XX_ICM4_USB_OHCI0_BASE UL(0xE1900000) +#define SPEAR6XX_ICM4_USB_EHCI1_BASE UL(0xE2000000) +#define SPEAR6XX_ICM4_USB_OHCI1_BASE UL(0xE2100000) +#define SPEAR6XX_ICM4_USB_ARB_BASE UL(0xE2800000) /* Debug uart for linux, will be used for debug and uncompress messages */ #define SPEAR_DBG_UART_BASE SPEAR6XX_ICM1_UART0_BASE diff --git a/arch/arm/mach-spear6xx/spear600.c b/arch/arm/mach-spear6xx/spear600.c index 5c484c433dc1..d0e6eeae9b04 100644 --- a/arch/arm/mach-spear6xx/spear600.c +++ b/arch/arm/mach-spear6xx/spear600.c @@ -14,7 +14,7 @@ #include <linux/ptrace.h> #include <asm/irq.h> #include <mach/generic.h> -#include <mach/spear.h> +#include <mach/hardware.h> /* Add spear600 specific devices here */ diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c index daff8d04f7b6..f19cefe91a2b 100644 --- a/arch/arm/mach-spear6xx/spear600_evb.c +++ b/arch/arm/mach-spear6xx/spear600_evb.c @@ -14,7 +14,7 @@ #include <asm/mach/arch.h> #include <asm/mach-types.h> #include <mach/generic.h> -#include <mach/spear.h> +#include <mach/hardware.h> static struct amba_device *amba_devs[] __initdata = { &gpio_device[0], @@ -46,6 +46,6 @@ MACHINE_START(SPEAR600, "ST-SPEAR600-EVB") .boot_params = 0x00000100, .map_io = spear6xx_map_io, .init_irq = spear6xx_init_irq, - .timer = &spear_sys_timer, + .timer = &spear6xx_timer, .init_machine = spear600_evb_init, MACHINE_END diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c index f2fe14e8471d..981812961ac7 100644 --- a/arch/arm/mach-spear6xx/spear6xx.c +++ b/arch/arm/mach-spear6xx/spear6xx.c @@ -18,9 +18,9 @@ #include <asm/hardware/vic.h> #include <asm/irq.h> #include <asm/mach/arch.h> -#include <mach/irqs.h> #include <mach/generic.h> -#include <mach/spear.h> +#include <mach/hardware.h> +#include <mach/irqs.h> /* Add spear6xx machines common devices here */ /* uart device registration */ @@ -31,8 +31,7 @@ struct amba_device uart_device[] = { }, .res = { .start = SPEAR6XX_ICM1_UART0_BASE, - .end = SPEAR6XX_ICM1_UART0_BASE + - SPEAR6XX_ICM1_UART0_SIZE - 1, + .end = SPEAR6XX_ICM1_UART0_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = {IRQ_UART_0, NO_IRQ}, @@ -42,8 +41,7 @@ struct amba_device uart_device[] = { }, .res = { .start = SPEAR6XX_ICM1_UART1_BASE, - .end = SPEAR6XX_ICM1_UART1_BASE + - SPEAR6XX_ICM1_UART1_SIZE - 1, + .end = SPEAR6XX_ICM1_UART1_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = {IRQ_UART_1, NO_IRQ}, @@ -72,8 +70,7 @@ struct amba_device gpio_device[] = { }, .res = { .start = SPEAR6XX_CPU_GPIO_BASE, - .end = SPEAR6XX_CPU_GPIO_BASE + - SPEAR6XX_CPU_GPIO_SIZE - 1, + .end = SPEAR6XX_CPU_GPIO_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = {IRQ_LOCAL_GPIO, NO_IRQ}, @@ -84,8 +81,7 @@ struct amba_device gpio_device[] = { }, .res = { .start = SPEAR6XX_ICM3_GPIO_BASE, - .end = SPEAR6XX_ICM3_GPIO_BASE + - SPEAR6XX_ICM3_GPIO_SIZE - 1, + .end = SPEAR6XX_ICM3_GPIO_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = {IRQ_BASIC_GPIO, NO_IRQ}, @@ -96,8 +92,7 @@ struct amba_device gpio_device[] = { }, .res = { .start = SPEAR6XX_ICM2_GPIO_BASE, - .end = SPEAR6XX_ICM2_GPIO_BASE + - SPEAR6XX_ICM2_GPIO_SIZE - 1, + .end = SPEAR6XX_ICM2_GPIO_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = {IRQ_APPL_GPIO, NO_IRQ}, @@ -122,27 +117,27 @@ static struct map_desc spear6xx_io_desc[] __initdata = { { .virtual = VA_SPEAR6XX_ICM1_UART0_BASE, .pfn = __phys_to_pfn(SPEAR6XX_ICM1_UART0_BASE), - .length = SPEAR6XX_ICM1_UART0_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, { .virtual = VA_SPEAR6XX_CPU_VIC_PRI_BASE, .pfn = __phys_to_pfn(SPEAR6XX_CPU_VIC_PRI_BASE), - .length = SPEAR6XX_CPU_VIC_PRI_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, { .virtual = VA_SPEAR6XX_CPU_VIC_SEC_BASE, .pfn = __phys_to_pfn(SPEAR6XX_CPU_VIC_SEC_BASE), - .length = SPEAR6XX_CPU_VIC_SEC_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, { .virtual = VA_SPEAR6XX_ICM3_SYS_CTRL_BASE, .pfn = __phys_to_pfn(SPEAR6XX_ICM3_SYS_CTRL_BASE), - .length = SPEAR6XX_ICM3_MISC_REG_BASE, + .length = SZ_4K, .type = MT_DEVICE }, { .virtual = VA_SPEAR6XX_ICM3_MISC_REG_BASE, .pfn = __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE), - .length = SPEAR6XX_ICM3_MISC_REG_SIZE, + .length = SZ_4K, .type = MT_DEVICE }, }; @@ -155,3 +150,34 @@ void __init spear6xx_map_io(void) /* This will initialize clock framework */ clk_init(); } + +static void __init spear6xx_timer_init(void) +{ + char pclk_name[] = "pll3_48m_clk"; + struct clk *gpt_clk, *pclk; + + /* get the system timer clock */ + gpt_clk = clk_get_sys("gpt0", NULL); + if (IS_ERR(gpt_clk)) { + pr_err("%s:couldn't get clk for gpt\n", __func__); + BUG(); + } + + /* get the suitable parent clock for timer*/ + pclk = clk_get(NULL, pclk_name); + if (IS_ERR(pclk)) { + pr_err("%s:couldn't get %s as parent for gpt\n", + __func__, pclk_name); + BUG(); + } + + clk_set_parent(gpt_clk, pclk); + clk_put(gpt_clk); + clk_put(pclk); + + spear_setup_timer(); +} + +struct sys_timer spear6xx_timer = { + .init = spear6xx_timer_init, +}; diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c index bd066206e110..ad8048801513 100644 --- a/arch/arm/mach-tegra/gpio.c +++ b/arch/arm/mach-tegra/gpio.c @@ -207,9 +207,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) spin_unlock_irqrestore(&bank->lvl_lock[port], flags); if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - __set_irq_handler_unlocked(irq, handle_level_irq); + __set_irq_handler_unlocked(d->irq, handle_level_irq); else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - __set_irq_handler_unlocked(irq, handle_edge_irq); + __set_irq_handler_unlocked(d->irq, handle_edge_irq); return 0; } diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h index d7723955dac7..a217f68ba57c 100644 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ b/arch/arm/mach-tegra/include/mach/clk.h @@ -20,6 +20,8 @@ #ifndef __MACH_CLK_H #define __MACH_CLK_H +struct clk; + void tegra_periph_reset_deassert(struct clk *c); void tegra_periph_reset_assert(struct clk *c); diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h index 412f5c63e65a..66cd3f4fc896 100644 --- a/arch/arm/mach-tegra/include/mach/clkdev.h +++ b/arch/arm/mach-tegra/include/mach/clkdev.h @@ -20,6 +20,8 @@ #ifndef __MACH_CLKDEV_H #define __MACH_CLKDEV_H +struct clk; + static inline int __clk_get(struct clk *clk) { return 1; diff --git a/arch/arm/mach-tegra/include/mach/kbc.h b/arch/arm/mach-tegra/include/mach/kbc.h new file mode 100644 index 000000000000..04c779832c78 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/kbc.h @@ -0,0 +1,62 @@ +/* + * Platform definitions for tegra-kbc keyboard input driver + * + * Copyright (c) 2010-2011, NVIDIA 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. + * + * 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 ASMARM_ARCH_TEGRA_KBC_H +#define ASMARM_ARCH_TEGRA_KBC_H + +#include <linux/types.h> +#include <linux/input/matrix_keypad.h> + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +#define KBC_MAX_GPIO 24 +#define KBC_MAX_KPENT 8 +#else +#define KBC_MAX_GPIO 20 +#define KBC_MAX_KPENT 7 +#endif + +#define KBC_MAX_ROW 16 +#define KBC_MAX_COL 8 +#define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) + +struct tegra_kbc_pin_cfg { + bool is_row; + unsigned char num; +}; + +struct tegra_kbc_wake_key { + u8 row:4; + u8 col:4; +}; + +struct tegra_kbc_platform_data { + unsigned int debounce_cnt; + unsigned int repeat_cnt; + + unsigned int wake_cnt; /* 0:wake on any key >1:wake on wake_cfg */ + const struct tegra_kbc_wake_key *wake_cfg; + + struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; + const struct matrix_keymap_data *keymap_data; + + bool wakeup; + bool use_fn_map; +}; +#endif diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index de7dfad6f769..17c74d21077c 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -46,24 +46,24 @@ #define ICTLR_COP_IER_CLR 0x38 #define ICTLR_COP_IEP_CLASS 0x3c -static void (*gic_mask_irq)(struct irq_data *d); -static void (*gic_unmask_irq)(struct irq_data *d); +static void (*tegra_gic_mask_irq)(struct irq_data *d); +static void (*tegra_gic_unmask_irq)(struct irq_data *d); -#define irq_to_ictlr(irq) (((irq)-32) >> 5) +#define irq_to_ictlr(irq) (((irq) - 32) >> 5) static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE); -#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100) +#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr) * 0x100) static void tegra_mask(struct irq_data *d) { void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq)); - gic_mask_irq(d); - writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_CLR); + tegra_gic_mask_irq(d); + writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR); } static void tegra_unmask(struct irq_data *d) { void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq)); - gic_unmask_irq(d); + tegra_gic_unmask_irq(d); writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET); } @@ -98,8 +98,8 @@ void __init tegra_init_irq(void) IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); gic = get_irq_chip(29); - gic_unmask_irq = gic->irq_unmask; - gic_mask_irq = gic->irq_mask; + tegra_gic_unmask_irq = gic->irq_unmask; + tegra_gic_mask_irq = gic->irq_mask; tegra_irq.irq_ack = gic->irq_ack; #ifdef CONFIG_SMP tegra_irq.irq_set_affinity = gic->irq_set_affinity; diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 247caa3400d0..203b986280f5 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -6,6 +6,7 @@ config UX500_SOC_COMMON select ARM_GIC select HAS_MTU select NOMADIK_GPIO + select ARM_ERRATA_753970 menu "Ux500 SoC" diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index a9ed3428a2fa..1edae65a0e72 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@ -19,6 +19,7 @@ #include <asm/mach/time.h> #include <asm/hardware/arm_timer.h> #include <asm/hardware/timer-sp.h> +#include <asm/hardware/sp810.h> #include <mach/motherboard.h> @@ -50,8 +51,16 @@ void __init v2m_map_io(struct map_desc *tile, size_t num) static void __init v2m_timer_init(void) { + u32 scctrl; + versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000); + /* Select 1MHz TIMCLK as the reference clock for SP804 timers */ + scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL)); + scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK; + scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK; + writel(scctrl, MMIO_P2V(V2M_SYSCTL + SCCTRL)); + writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig new file mode 100644 index 000000000000..2c20a341c11a --- /dev/null +++ b/arch/arm/mach-vt8500/Kconfig @@ -0,0 +1,73 @@ +if ARCH_VT8500 + +config VTWM_VERSION_VT8500 + bool + +config VTWM_VERSION_WM8505 + bool + +config MACH_BV07 + bool "Benign BV07-8500 Mini Netbook" + depends on ARCH_VT8500 + select VTWM_VERSION_VT8500 + help + Add support for the inexpensive 7-inch netbooks sold by many + Chinese distributors under various names. Note that there are + many hardware implementations in identical exterior, make sure + that yours is indeed based on a VIA VT8500 chip. + +config MACH_WM8505_7IN_NETBOOK + bool "WM8505 7-inch generic netbook" + depends on ARCH_VT8500 + select VTWM_VERSION_WM8505 + help + Add support for the inexpensive 7-inch netbooks sold by many + Chinese distributors under various names. Note that there are + many hardware implementations in identical exterior, make sure + that yours is indeed based on a WonderMedia WM8505 chip. + +comment "LCD panel size" + +config WMT_PANEL_800X480 + bool "7-inch with 800x480 resolution" + depends on (FB_VT8500 || FB_WM8505) + default y + help + These are found in most of the netbooks in generic cases, as + well as in Eken M001 tablets and possibly elsewhere. + + To select this panel at runtime, say y here and append + 'panel=800x480' to your kernel command line. Otherwise, the + largest one available will be used. + +config WMT_PANEL_800X600 + bool "8-inch with 800x600 resolution" + depends on (FB_VT8500 || FB_WM8505) + help + These are found in Eken M003 tablets and possibly elsewhere. + + To select this panel at runtime, say y here and append + 'panel=800x600' to your kernel command line. Otherwise, the + largest one available will be used. + +config WMT_PANEL_1024X576 + bool "10-inch with 1024x576 resolution" + depends on (FB_VT8500 || FB_WM8505) + help + These are found in CherryPal netbooks and possibly elsewhere. + + To select this panel at runtime, say y here and append + 'panel=1024x576' to your kernel command line. Otherwise, the + largest one available will be used. + +config WMT_PANEL_1024X600 + bool "10-inch with 1024x600 resolution" + depends on (FB_VT8500 || FB_WM8505) + help + These are found in Eken M006 tablets and possibly elsewhere. + + To select this panel at runtime, say y here and append + 'panel=1024x600' to your kernel command line. Otherwise, the + largest one available will be used. + +endif diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile new file mode 100644 index 000000000000..81aedb7c893c --- /dev/null +++ b/arch/arm/mach-vt8500/Makefile @@ -0,0 +1,9 @@ +obj-y += devices.o gpio.o irq.o timer.o + +obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o +obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o + +obj-$(CONFIG_MACH_BV07) += bv07.o +obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o + +obj-$(CONFIG_HAVE_PWM) += pwm.o diff --git a/arch/arm/mach-vt8500/Makefile.boot b/arch/arm/mach-vt8500/Makefile.boot new file mode 100644 index 000000000000..a8acc4e24902 --- /dev/null +++ b/arch/arm/mach-vt8500/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x01000000 diff --git a/arch/arm/mach-vt8500/bv07.c b/arch/arm/mach-vt8500/bv07.c new file mode 100644 index 000000000000..94a261d86bf0 --- /dev/null +++ b/arch/arm/mach-vt8500/bv07.c @@ -0,0 +1,77 @@ +/* + * arch/arm/mach-vt8500/bv07.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 + */ + +#include <linux/io.h> +#include <linux/pm.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +#include "devices.h" + +static void __iomem *pmc_hiber; + +static struct platform_device *devices[] __initdata = { + &vt8500_device_uart0, + &vt8500_device_lcdc, + &vt8500_device_ehci, + &vt8500_device_ge_rops, + &vt8500_device_pwm, + &vt8500_device_pwmbl, + &vt8500_device_rtc, +}; + +static void vt8500_power_off(void) +{ + local_irq_disable(); + writew(5, pmc_hiber); + asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0)); +} + +void __init bv07_init(void) +{ +#ifdef CONFIG_FB_VT8500 + void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4); + if (gpio_mux_reg) { + writel(readl(gpio_mux_reg) | 1, gpio_mux_reg); + iounmap(gpio_mux_reg); + } else { + printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n"); + } +#endif + pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2); + if (pmc_hiber) + pm_power_off = &vt8500_power_off; + else + printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n"); + + vt8500_set_resources(); + platform_add_devices(devices, ARRAY_SIZE(devices)); + vt8500_gpio_init(); +} + +MACHINE_START(BV07, "Benign BV07 Mini Netbook") + .boot_params = 0x00000100, + .reserve = vt8500_reserve_mem, + .map_io = vt8500_map_io, + .init_irq = vt8500_init_irq, + .timer = &vt8500_timer, + .init_machine = bv07_init, +MACHINE_END diff --git a/arch/arm/mach-vt8500/devices-vt8500.c b/arch/arm/mach-vt8500/devices-vt8500.c new file mode 100644 index 000000000000..19519aeecf37 --- /dev/null +++ b/arch/arm/mach-vt8500/devices-vt8500.c @@ -0,0 +1,91 @@ +/* linux/arch/arm/mach-vt8500/devices-vt8500.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <linux/platform_device.h> + +#include <mach/vt8500_regs.h> +#include <mach/vt8500_irqs.h> +#include <mach/i8042.h> +#include "devices.h" + +void __init vt8500_set_resources(void) +{ + struct resource tmp[3]; + + tmp[0] = wmt_mmio_res(VT8500_LCDC_BASE, SZ_1K); + tmp[1] = wmt_irq_res(IRQ_LCDC); + wmt_res_add(&vt8500_device_lcdc, tmp, 2); + + tmp[0] = wmt_mmio_res(VT8500_UART0_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART0); + wmt_res_add(&vt8500_device_uart0, tmp, 2); + + tmp[0] = wmt_mmio_res(VT8500_UART1_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART1); + wmt_res_add(&vt8500_device_uart1, tmp, 2); + + tmp[0] = wmt_mmio_res(VT8500_UART2_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART2); + wmt_res_add(&vt8500_device_uart2, tmp, 2); + + tmp[0] = wmt_mmio_res(VT8500_UART3_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART3); + wmt_res_add(&vt8500_device_uart3, tmp, 2); + + tmp[0] = wmt_mmio_res(VT8500_EHCI_BASE, SZ_512); + tmp[1] = wmt_irq_res(IRQ_EHCI); + wmt_res_add(&vt8500_device_ehci, tmp, 2); + + tmp[0] = wmt_mmio_res(VT8500_GEGEA_BASE, SZ_256); + wmt_res_add(&vt8500_device_ge_rops, tmp, 1); + + tmp[0] = wmt_mmio_res(VT8500_PWM_BASE, 0x44); + wmt_res_add(&vt8500_device_pwm, tmp, 1); + + tmp[0] = wmt_mmio_res(VT8500_RTC_BASE, 0x2c); + tmp[1] = wmt_irq_res(IRQ_RTC); + tmp[2] = wmt_irq_res(IRQ_RTCSM); + wmt_res_add(&vt8500_device_rtc, tmp, 3); +} + +static void __init vt8500_set_externs(void) +{ + /* Non-resource-aware stuff */ + wmt_ic_base = VT8500_IC_BASE; + wmt_gpio_base = VT8500_GPIO_BASE; + wmt_pmc_base = VT8500_PMC_BASE; + wmt_i8042_base = VT8500_PS2_BASE; + + wmt_nr_irqs = VT8500_NR_IRQS; + wmt_timer_irq = IRQ_PMCOS0; + wmt_gpio_ext_irq[0] = IRQ_EXT0; + wmt_gpio_ext_irq[1] = IRQ_EXT1; + wmt_gpio_ext_irq[2] = IRQ_EXT2; + wmt_gpio_ext_irq[3] = IRQ_EXT3; + wmt_gpio_ext_irq[4] = IRQ_EXT4; + wmt_gpio_ext_irq[5] = IRQ_EXT5; + wmt_gpio_ext_irq[6] = IRQ_EXT6; + wmt_gpio_ext_irq[7] = IRQ_EXT7; + wmt_i8042_kbd_irq = IRQ_PS2KBD; + wmt_i8042_aux_irq = IRQ_PS2MOUSE; +} + +void __init vt8500_map_io(void) +{ + iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc)); + + /* Should be done before interrupts and timers are initialized */ + vt8500_set_externs(); +} diff --git a/arch/arm/mach-vt8500/devices-wm8505.c b/arch/arm/mach-vt8500/devices-wm8505.c new file mode 100644 index 000000000000..db4594e029f4 --- /dev/null +++ b/arch/arm/mach-vt8500/devices-wm8505.c @@ -0,0 +1,99 @@ +/* linux/arch/arm/mach-vt8500/devices-wm8505.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <linux/platform_device.h> + +#include <mach/wm8505_regs.h> +#include <mach/wm8505_irqs.h> +#include <mach/i8042.h> +#include "devices.h" + +void __init wm8505_set_resources(void) +{ + struct resource tmp[3]; + + tmp[0] = wmt_mmio_res(WM8505_GOVR_BASE, SZ_512); + wmt_res_add(&vt8500_device_wm8505_fb, tmp, 1); + + tmp[0] = wmt_mmio_res(WM8505_UART0_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART0); + wmt_res_add(&vt8500_device_uart0, tmp, 2); + + tmp[0] = wmt_mmio_res(WM8505_UART1_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART1); + wmt_res_add(&vt8500_device_uart1, tmp, 2); + + tmp[0] = wmt_mmio_res(WM8505_UART2_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART2); + wmt_res_add(&vt8500_device_uart2, tmp, 2); + + tmp[0] = wmt_mmio_res(WM8505_UART3_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART3); + wmt_res_add(&vt8500_device_uart3, tmp, 2); + + tmp[0] = wmt_mmio_res(WM8505_UART4_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART4); + wmt_res_add(&vt8500_device_uart4, tmp, 2); + + tmp[0] = wmt_mmio_res(WM8505_UART5_BASE, 0x1040); + tmp[1] = wmt_irq_res(IRQ_UART5); + wmt_res_add(&vt8500_device_uart5, tmp, 2); + + tmp[0] = wmt_mmio_res(WM8505_EHCI_BASE, SZ_512); + tmp[1] = wmt_irq_res(IRQ_EHCI); + wmt_res_add(&vt8500_device_ehci, tmp, 2); + + tmp[0] = wmt_mmio_res(WM8505_GEGEA_BASE, SZ_256); + wmt_res_add(&vt8500_device_ge_rops, tmp, 1); + + tmp[0] = wmt_mmio_res(WM8505_PWM_BASE, 0x44); + wmt_res_add(&vt8500_device_pwm, tmp, 1); + + tmp[0] = wmt_mmio_res(WM8505_RTC_BASE, 0x2c); + tmp[1] = wmt_irq_res(IRQ_RTC); + tmp[2] = wmt_irq_res(IRQ_RTCSM); + wmt_res_add(&vt8500_device_rtc, tmp, 3); +} + +static void __init wm8505_set_externs(void) +{ + /* Non-resource-aware stuff */ + wmt_ic_base = WM8505_IC_BASE; + wmt_sic_base = WM8505_SIC_BASE; + wmt_gpio_base = WM8505_GPIO_BASE; + wmt_pmc_base = WM8505_PMC_BASE; + wmt_i8042_base = WM8505_PS2_BASE; + + wmt_nr_irqs = WM8505_NR_IRQS; + wmt_timer_irq = IRQ_PMCOS0; + wmt_gpio_ext_irq[0] = IRQ_EXT0; + wmt_gpio_ext_irq[1] = IRQ_EXT1; + wmt_gpio_ext_irq[2] = IRQ_EXT2; + wmt_gpio_ext_irq[3] = IRQ_EXT3; + wmt_gpio_ext_irq[4] = IRQ_EXT4; + wmt_gpio_ext_irq[5] = IRQ_EXT5; + wmt_gpio_ext_irq[6] = IRQ_EXT6; + wmt_gpio_ext_irq[7] = IRQ_EXT7; + wmt_i8042_kbd_irq = IRQ_PS2KBD; + wmt_i8042_aux_irq = IRQ_PS2MOUSE; +} + +void __init wm8505_map_io(void) +{ + iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc)); + + /* Should be done before interrupts and timers are initialized */ + wm8505_set_externs(); +} diff --git a/arch/arm/mach-vt8500/devices.c b/arch/arm/mach-vt8500/devices.c new file mode 100644 index 000000000000..1fcdc36b358d --- /dev/null +++ b/arch/arm/mach-vt8500/devices.c @@ -0,0 +1,270 @@ +/* linux/arch/arm/mach-vt8500/devices.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/pwm_backlight.h> +#include <linux/memblock.h> + +#include <asm/mach/arch.h> + +#include <mach/vt8500fb.h> +#include <mach/i8042.h> +#include "devices.h" + +/* These can't use resources currently */ +unsigned long wmt_ic_base __initdata; +unsigned long wmt_sic_base __initdata; +unsigned long wmt_gpio_base __initdata; +unsigned long wmt_pmc_base __initdata; +unsigned long wmt_i8042_base __initdata; + +int wmt_nr_irqs __initdata; +int wmt_timer_irq __initdata; +int wmt_gpio_ext_irq[8] __initdata; + +/* Should remain accessible after init. + * i8042 driver desperately calls for attention... + */ +int wmt_i8042_kbd_irq; +int wmt_i8042_aux_irq; + +static u64 fb_dma_mask = DMA_BIT_MASK(32); + +struct platform_device vt8500_device_lcdc = { + .name = "vt8500-lcd", + .id = 0, + .dev = { + .dma_mask = &fb_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +struct platform_device vt8500_device_wm8505_fb = { + .name = "wm8505-fb", + .id = 0, +}; + +/* Smallest to largest */ +static struct vt8500fb_platform_data panels[] = { +#ifdef CONFIG_WMT_PANEL_800X480 +{ + .xres_virtual = 800, + .yres_virtual = 480 * 2, + .mode = { + .name = "800x480", + .xres = 800, + .yres = 480, + .left_margin = 88, + .right_margin = 40, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 0, + .vsync_len = 1, + .vmode = FB_VMODE_NONINTERLACED, + }, +}, +#endif +#ifdef CONFIG_WMT_PANEL_800X600 +{ + .xres_virtual = 800, + .yres_virtual = 600 * 2, + .mode = { + .name = "800x600", + .xres = 800, + .yres = 600, + .left_margin = 88, + .right_margin = 40, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 0, + .vsync_len = 1, + .vmode = FB_VMODE_NONINTERLACED, + }, +}, +#endif +#ifdef CONFIG_WMT_PANEL_1024X576 +{ + .xres_virtual = 1024, + .yres_virtual = 576 * 2, + .mode = { + .name = "1024x576", + .xres = 1024, + .yres = 576, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, + }, +}, +#endif +#ifdef CONFIG_WMT_PANEL_1024X600 +{ + .xres_virtual = 1024, + .yres_virtual = 600 * 2, + .mode = { + .name = "1024x600", + .xres = 1024, + .yres = 600, + .left_margin = 66, + .right_margin = 2, + .upper_margin = 19, + .lower_margin = 1, + .hsync_len = 23, + .vsync_len = 8, + .vmode = FB_VMODE_NONINTERLACED, + }, +}, +#endif +}; + +static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1; + +static int __init panel_setup(char *str) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(panels); i++) { + if (strcmp(panels[i].mode.name, str) == 0) { + current_panel_idx = i; + break; + } + } + return 0; +} + +early_param("panel", panel_setup); + +static inline void preallocate_fb(struct vt8500fb_platform_data *p, + unsigned long align) { + p->video_mem_len = (p->xres_virtual * p->yres_virtual * 4) >> + (p->bpp > 16 ? 0 : (p->bpp > 8 ? 1 : + (8 / p->bpp) + 1)); + p->video_mem_phys = (unsigned long)memblock_alloc(p->video_mem_len, + align); + p->video_mem_virt = phys_to_virt(p->video_mem_phys); +} + +struct platform_device vt8500_device_uart0 = { + .name = "vt8500_serial", + .id = 0, +}; + +struct platform_device vt8500_device_uart1 = { + .name = "vt8500_serial", + .id = 1, +}; + +struct platform_device vt8500_device_uart2 = { + .name = "vt8500_serial", + .id = 2, +}; + +struct platform_device vt8500_device_uart3 = { + .name = "vt8500_serial", + .id = 3, +}; + +struct platform_device vt8500_device_uart4 = { + .name = "vt8500_serial", + .id = 4, +}; + +struct platform_device vt8500_device_uart5 = { + .name = "vt8500_serial", + .id = 5, +}; + +static u64 ehci_dma_mask = DMA_BIT_MASK(32); + +struct platform_device vt8500_device_ehci = { + .name = "vt8500-ehci", + .id = 0, + .dev = { + .dma_mask = &ehci_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +struct platform_device vt8500_device_ge_rops = { + .name = "wmt_ge_rops", + .id = -1, +}; + +struct platform_device vt8500_device_pwm = { + .name = "vt8500-pwm", + .id = 0, +}; + +static struct platform_pwm_backlight_data vt8500_pwmbl_data = { + .pwm_id = 0, + .max_brightness = 128, + .dft_brightness = 70, + .pwm_period_ns = 250000, /* revisit when clocks are implemented */ +}; + +struct platform_device vt8500_device_pwmbl = { + .name = "pwm-backlight", + .id = 0, + .dev = { + .platform_data = &vt8500_pwmbl_data, + }, +}; + +struct platform_device vt8500_device_rtc = { + .name = "vt8500-rtc", + .id = 0, +}; + +struct map_desc wmt_io_desc[] __initdata = { + /* SoC MMIO registers */ + [0] = { + .virtual = 0xf8000000, + .pfn = __phys_to_pfn(0xd8000000), + .length = 0x00390000, /* max of all chip variants */ + .type = MT_DEVICE + }, + /* PCI I/O space, numbers tied to those in <mach/io.h> */ + [1] = { + .virtual = 0xf0000000, + .pfn = __phys_to_pfn(0xc0000000), + .length = SZ_64K, + .type = MT_DEVICE + }, +}; + +void __init vt8500_reserve_mem(void) +{ +#ifdef CONFIG_FB_VT8500 + panels[current_panel_idx].bpp = 16; /* Always use RGB565 */ + preallocate_fb(&panels[current_panel_idx], SZ_4M); + vt8500_device_lcdc.dev.platform_data = &panels[current_panel_idx]; +#endif +} + +void __init wm8505_reserve_mem(void) +{ +#if defined CONFIG_FB_WM8505 + panels[current_panel_idx].bpp = 32; /* Always use RGB888 */ + preallocate_fb(&panels[current_panel_idx], 32); + vt8500_device_wm8505_fb.dev.platform_data = &panels[current_panel_idx]; +#endif +} diff --git a/arch/arm/mach-vt8500/devices.h b/arch/arm/mach-vt8500/devices.h new file mode 100644 index 000000000000..188d4e17f35c --- /dev/null +++ b/arch/arm/mach-vt8500/devices.h @@ -0,0 +1,88 @@ +/* linux/arch/arm/mach-vt8500/devices.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef __ARCH_ARM_MACH_VT8500_DEVICES_H +#define __ARCH_ARM_MACH_VT8500_DEVICES_H + +#include <linux/platform_device.h> +#include <asm/mach/map.h> + +void __init vt8500_init_irq(void); +void __init wm8505_init_irq(void); +void __init vt8500_map_io(void); +void __init wm8505_map_io(void); +void __init vt8500_reserve_mem(void); +void __init wm8505_reserve_mem(void); +void __init vt8500_gpio_init(void); +void __init vt8500_set_resources(void); +void __init wm8505_set_resources(void); + +extern unsigned long wmt_ic_base __initdata; +extern unsigned long wmt_sic_base __initdata; +extern unsigned long wmt_gpio_base __initdata; +extern unsigned long wmt_pmc_base __initdata; + +extern int wmt_nr_irqs __initdata; +extern int wmt_timer_irq __initdata; +extern int wmt_gpio_ext_irq[8] __initdata; + +extern struct map_desc wmt_io_desc[2] __initdata; + +static inline struct resource wmt_mmio_res(u32 start, u32 size) +{ + struct resource tmp = { + .flags = IORESOURCE_MEM, + .start = start, + .end = start + size - 1, + }; + + return tmp; +} + +static inline struct resource wmt_irq_res(int irq) +{ + struct resource tmp = { + .flags = IORESOURCE_IRQ, + .start = irq, + .end = irq, + }; + + return tmp; +} + +static inline void wmt_res_add(struct platform_device *pdev, + const struct resource *res, unsigned int num) +{ + if (unlikely(platform_device_add_resources(pdev, res, num))) + pr_err("Failed to assign resources\n"); +} + +extern struct sys_timer vt8500_timer; + +extern struct platform_device vt8500_device_uart0; +extern struct platform_device vt8500_device_uart1; +extern struct platform_device vt8500_device_uart2; +extern struct platform_device vt8500_device_uart3; +extern struct platform_device vt8500_device_uart4; +extern struct platform_device vt8500_device_uart5; + +extern struct platform_device vt8500_device_lcdc; +extern struct platform_device vt8500_device_wm8505_fb; +extern struct platform_device vt8500_device_ehci; +extern struct platform_device vt8500_device_ge_rops; +extern struct platform_device vt8500_device_pwm; +extern struct platform_device vt8500_device_pwmbl; +extern struct platform_device vt8500_device_rtc; +#endif diff --git a/arch/arm/mach-vt8500/gpio.c b/arch/arm/mach-vt8500/gpio.c new file mode 100644 index 000000000000..2bcc0ec783df --- /dev/null +++ b/arch/arm/mach-vt8500/gpio.c @@ -0,0 +1,240 @@ +/* linux/arch/arm/mach-vt8500/gpio.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#include <linux/gpio.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include "devices.h" + +#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip) + +#define ENABLE_REGS 0x0 +#define DIRECTION_REGS 0x20 +#define OUTVALUE_REGS 0x40 +#define INVALUE_REGS 0x60 + +#define EXT_REGOFF 0x1c + +static void __iomem *regbase; + +struct vt8500_gpio_chip { + struct gpio_chip chip; + unsigned int shift; + unsigned int regoff; +}; + +static int gpio_to_irq_map[8]; + +static int vt8500_muxed_gpio_request(struct gpio_chip *chip, + unsigned offset) +{ + struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); + unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff); + + val |= (1 << vt8500_chip->shift << offset); + writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff); + + return 0; +} + +static void vt8500_muxed_gpio_free(struct gpio_chip *chip, + unsigned offset) +{ + struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); + unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff); + + val &= ~(1 << vt8500_chip->shift << offset); + writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff); +} + +static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); + unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff); + + val &= ~(1 << vt8500_chip->shift << offset); + writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff); + + return 0; +} + +static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); + unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff); + + val |= (1 << vt8500_chip->shift << offset); + writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff); + + if (value) { + val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff); + val |= (1 << vt8500_chip->shift << offset); + writel(val, regbase + OUTVALUE_REGS + vt8500_chip->regoff); + } + return 0; +} + +static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip, + unsigned offset) +{ + struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); + + return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff) + >> vt8500_chip->shift >> offset) & 1; +} + +static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); + unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff); + + if (value) + val |= (1 << vt8500_chip->shift << offset); + else + val &= ~(1 << vt8500_chip->shift << offset); + + writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff); +} + +#define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num) \ +{ \ + .chip = { \ + .label = __name, \ + .request = vt8500_muxed_gpio_request, \ + .free = vt8500_muxed_gpio_free, \ + .direction_input = vt8500_muxed_gpio_direction_input, \ + .direction_output = vt8500_muxed_gpio_direction_output, \ + .get = vt8500_muxed_gpio_get_value, \ + .set = vt8500_muxed_gpio_set_value, \ + .can_sleep = 0, \ + .base = __base, \ + .ngpio = __num, \ + }, \ + .shift = __shift, \ + .regoff = __off, \ +} + +static struct vt8500_gpio_chip vt8500_muxed_gpios[] = { + VT8500_GPIO_BANK("uart0", 0, 0x0, 8, 4), + VT8500_GPIO_BANK("uart1", 4, 0x0, 12, 4), + VT8500_GPIO_BANK("spi0", 8, 0x0, 16, 4), + VT8500_GPIO_BANK("spi1", 12, 0x0, 20, 4), + VT8500_GPIO_BANK("spi2", 16, 0x0, 24, 4), + VT8500_GPIO_BANK("pwmout", 24, 0x0, 28, 2), + + VT8500_GPIO_BANK("sdmmc", 0, 0x4, 30, 11), + VT8500_GPIO_BANK("ms", 16, 0x4, 41, 7), + VT8500_GPIO_BANK("i2c0", 24, 0x4, 48, 2), + VT8500_GPIO_BANK("i2c1", 26, 0x4, 50, 2), + + VT8500_GPIO_BANK("mii", 0, 0x8, 52, 20), + VT8500_GPIO_BANK("see", 20, 0x8, 72, 4), + VT8500_GPIO_BANK("ide", 24, 0x8, 76, 7), + + VT8500_GPIO_BANK("ccir", 0, 0xc, 83, 19), + + VT8500_GPIO_BANK("ts", 8, 0x10, 102, 11), + + VT8500_GPIO_BANK("lcd", 0, 0x14, 113, 23), +}; + +static int vt8500_gpio_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF); + + val &= ~(1 << offset); + writel(val, regbase + DIRECTION_REGS + EXT_REGOFF); + return 0; +} + +static int vt8500_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF); + + val |= (1 << offset); + writel(val, regbase + DIRECTION_REGS + EXT_REGOFF); + + if (value) { + val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF); + val |= (1 << offset); + writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF); + } + return 0; +} + +static int vt8500_gpio_get_value(struct gpio_chip *chip, + unsigned offset) +{ + return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1; +} + +static void vt8500_gpio_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF); + + if (value) + val |= (1 << offset); + else + val &= ~(1 << offset); + + writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF); +} + +static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + if (offset > 7) + return -EINVAL; + + return gpio_to_irq_map[offset]; +} + +static struct gpio_chip vt8500_external_gpios = { + .label = "extgpio", + .direction_input = vt8500_gpio_direction_input, + .direction_output = vt8500_gpio_direction_output, + .get = vt8500_gpio_get_value, + .set = vt8500_gpio_set_value, + .to_irq = vt8500_gpio_to_irq, + .can_sleep = 0, + .base = 0, + .ngpio = 8, +}; + +void __init vt8500_gpio_init(void) +{ + int i; + + for (i = 0; i < 8; i++) + gpio_to_irq_map[i] = wmt_gpio_ext_irq[i]; + + regbase = ioremap(wmt_gpio_base, SZ_64K); + if (!regbase) { + printk(KERN_ERR "Failed to map MMIO registers for GPIO\n"); + return; + } + + gpiochip_add(&vt8500_external_gpios); + + for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++) + gpiochip_add(&vt8500_muxed_gpios[i].chip); +} diff --git a/arch/arm/mach-vt8500/include/mach/debug-macro.S b/arch/arm/mach-vt8500/include/mach/debug-macro.S new file mode 100644 index 000000000000..f1191626ad51 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/debug-macro.S @@ -0,0 +1,31 @@ +/* + * arch/arm/mach-vt8500/include/mach/debug-macro.S + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * Debugging macro include header + * + * 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, rp, rv + mov \rp, #0x00200000 + orr \rv, \rp, #0xf8000000 + orr \rp, \rp, #0xd8000000 + .endm + + .macro senduart,rd,rx + strb \rd, [\rx, #0] + .endm + + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x1c] + ands \rd, \rd, #0x2 + bne 1001b + .endm + + .macro waituart,rd,rx + .endm diff --git a/arch/arm/mach-vt8500/include/mach/entry-macro.S b/arch/arm/mach-vt8500/include/mach/entry-macro.S new file mode 100644 index 000000000000..92684c7eaed3 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/entry-macro.S @@ -0,0 +1,32 @@ +/* + * arch/arm/mach-vt8500/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for VIA VT8500 + * + * 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. + */ + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + @ physical 0xd8140000 is virtual 0xf8140000 + mov \base, #0xf8000000 + orr \base, \base, #0x00140000 + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqnr, [\base] + cmp \irqnr, #63 @ may be false positive, check interrupt status + bne 1001f + ldr \irqstat, [\base, #0x84] + ands \irqstat, #0x80000000 + moveq \irqnr, #0 +1001: + .endm + diff --git a/arch/arm/mach-vt8500/include/mach/gpio.h b/arch/arm/mach-vt8500/include/mach/gpio.h new file mode 100644 index 000000000000..94ff27678a46 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/gpio.h @@ -0,0 +1,6 @@ +#include <asm-generic/gpio.h> + +#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 diff --git a/arch/arm/mach-vt8500/include/mach/hardware.h b/arch/arm/mach-vt8500/include/mach/hardware.h new file mode 100644 index 000000000000..db4163f72c39 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/hardware.h @@ -0,0 +1,12 @@ +/* arch/arm/mach-vt8500/include/mach/hardware.h + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ diff --git a/arch/arm/mach-vt8500/include/mach/i8042.h b/arch/arm/mach-vt8500/include/mach/i8042.h new file mode 100644 index 000000000000..cd7143cad6f3 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/i8042.h @@ -0,0 +1,18 @@ +/* arch/arm/mach-vt8500/include/mach/i8042.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +extern unsigned long wmt_i8042_base __initdata; +extern int wmt_i8042_kbd_irq; +extern int wmt_i8042_aux_irq; diff --git a/arch/arm/mach-vt8500/include/mach/io.h b/arch/arm/mach-vt8500/include/mach/io.h new file mode 100644 index 000000000000..9077239f78c9 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/io.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-vt8500/include/mach/io.h + * + * Copyright (C) 2010 Alexey Charkov + * + * 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_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffff + +#define __io(a) __typesafe_io((a) + 0xf0000000) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-vt8500/include/mach/irqs.h b/arch/arm/mach-vt8500/include/mach/irqs.h new file mode 100644 index 000000000000..a129fd1222fb --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/irqs.h @@ -0,0 +1,22 @@ +/* + * arch/arm/mach-vt8500/include/mach/irqs.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 + */ + +/* This value is just to make the core happy, never used otherwise */ +#define NR_IRQS 128 diff --git a/arch/arm/mach-vt8500/include/mach/memory.h b/arch/arm/mach-vt8500/include/mach/memory.h new file mode 100644 index 000000000000..175f914eff93 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/memory.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-vt8500/include/mach/memory.h + * + * Copyright (C) 2003 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-vt8500/include/mach/system.h b/arch/arm/mach-vt8500/include/mach/system.h new file mode 100644 index 000000000000..d6c757eaf26b --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/system.h @@ -0,0 +1,18 @@ +/* + * arch/arm/mach-vt8500/include/mach/system.h + * + */ +#include <asm/io.h> + +/* PM Software Reset request register */ +#define VT8500_PMSR_VIRT 0xf8130060 + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ + writel(1, VT8500_PMSR_VIRT); +} diff --git a/arch/arm/mach-vt8500/include/mach/timex.h b/arch/arm/mach-vt8500/include/mach/timex.h new file mode 100644 index 000000000000..8487e4c690b7 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/timex.h @@ -0,0 +1,26 @@ +/* + * arch/arm/mach-vt8500/include/mach/timex.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@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_TIMEX_H +#define MACH_TIMEX_H + +#define CLOCK_TICK_RATE (3000000) + +#endif /* MACH_TIMEX_H */ diff --git a/arch/arm/mach-vt8500/include/mach/uncompress.h b/arch/arm/mach-vt8500/include/mach/uncompress.h new file mode 100644 index 000000000000..bb9e2d23fee3 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/uncompress.h @@ -0,0 +1,37 @@ +/* arch/arm/mach-vt8500/include/mach/uncompress.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * Based on arch/arm/mach-dove/include/mach/uncompress.h + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#define UART0_PHYS 0xd8200000 +#include <asm/io.h> + +static void putc(const char c) +{ + while (readb(UART0_PHYS + 0x1c) & 0x2) + /* Tx busy, wait and poll */; + + writeb(c, UART0_PHYS); +} + +static void flush(void) +{ +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/arch/arm/mach-vt8500/include/mach/vmalloc.h b/arch/arm/mach-vt8500/include/mach/vmalloc.h new file mode 100644 index 000000000000..4642290ce416 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/vmalloc.h @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-vt8500/include/mach/vmalloc.h + * + * Copyright (C) 2000 Russell King. + * + * 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 + */ +#define VMALLOC_END 0xd0000000UL diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h b/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h new file mode 100644 index 000000000000..ecfee9124711 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h @@ -0,0 +1,88 @@ +/* + * arch/arm/mach-vt8500/include/mach/vt8500_irqs.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 + */ + +/* VT8500 Interrupt Sources */ + +#define IRQ_JPEGENC 0 /* JPEG Encoder */ +#define IRQ_JPEGDEC 1 /* JPEG Decoder */ + /* Reserved */ +#define IRQ_PATA 3 /* PATA Controller */ + /* Reserved */ +#define IRQ_DMA 5 /* DMA Controller */ +#define IRQ_EXT0 6 /* External Interrupt 0 */ +#define IRQ_EXT1 7 /* External Interrupt 1 */ +#define IRQ_GE 8 /* Graphic Engine */ +#define IRQ_GOV 9 /* Graphic Overlay Engine */ +#define IRQ_ETHER 10 /* Ethernet MAC */ +#define IRQ_MPEGTS 11 /* Transport Stream Interface */ +#define IRQ_LCDC 12 /* LCD Controller */ +#define IRQ_EXT2 13 /* External Interrupt 2 */ +#define IRQ_EXT3 14 /* External Interrupt 3 */ +#define IRQ_EXT4 15 /* External Interrupt 4 */ +#define IRQ_CIPHER 16 /* Cipher */ +#define IRQ_VPP 17 /* Video Post-Processor */ +#define IRQ_I2C1 18 /* I2C 1 */ +#define IRQ_I2C0 19 /* I2C 0 */ +#define IRQ_SDMMC 20 /* SD/MMC Controller */ +#define IRQ_SDMMC_DMA 21 /* SD/MMC Controller DMA */ +#define IRQ_PMC_WU 22 /* Power Management Controller Wakeup */ + /* Reserved */ +#define IRQ_SPI0 24 /* SPI 0 */ +#define IRQ_SPI1 25 /* SPI 1 */ +#define IRQ_SPI2 26 /* SPI 2 */ +#define IRQ_LCDDF 27 /* LCD Data Formatter */ +#define IRQ_NAND 28 /* NAND Flash Controller */ +#define IRQ_NAND_DMA 29 /* NAND Flash Controller DMA */ +#define IRQ_MS 30 /* MemoryStick Controller */ +#define IRQ_MS_DMA 31 /* MemoryStick Controller DMA */ +#define IRQ_UART0 32 /* UART 0 */ +#define IRQ_UART1 33 /* UART 1 */ +#define IRQ_I2S 34 /* I2S */ +#define IRQ_PCM 35 /* PCM */ +#define IRQ_PMCOS0 36 /* PMC OS Timer 0 */ +#define IRQ_PMCOS1 37 /* PMC OS Timer 1 */ +#define IRQ_PMCOS2 38 /* PMC OS Timer 2 */ +#define IRQ_PMCOS3 39 /* PMC OS Timer 3 */ +#define IRQ_VPU 40 /* Video Processing Unit */ +#define IRQ_VID 41 /* Video Digital Input Interface */ +#define IRQ_AC97 42 /* AC97 Interface */ +#define IRQ_EHCI 43 /* USB */ +#define IRQ_NOR 44 /* NOR Flash Controller */ +#define IRQ_PS2MOUSE 45 /* PS/2 Mouse */ +#define IRQ_PS2KBD 46 /* PS/2 Keyboard */ +#define IRQ_UART2 47 /* UART 2 */ +#define IRQ_RTC 48 /* RTC Interrupt */ +#define IRQ_RTCSM 49 /* RTC Second/Minute Update Interrupt */ +#define IRQ_UART3 50 /* UART 3 */ +#define IRQ_ADC 51 /* ADC */ +#define IRQ_EXT5 52 /* External Interrupt 5 */ +#define IRQ_EXT6 53 /* External Interrupt 6 */ +#define IRQ_EXT7 54 /* External Interrupt 7 */ +#define IRQ_CIR 55 /* CIR */ +#define IRQ_DMA0 56 /* DMA Channel 0 */ +#define IRQ_DMA1 57 /* DMA Channel 1 */ +#define IRQ_DMA2 58 /* DMA Channel 2 */ +#define IRQ_DMA3 59 /* DMA Channel 3 */ +#define IRQ_DMA4 60 /* DMA Channel 4 */ +#define IRQ_DMA5 61 /* DMA Channel 5 */ +#define IRQ_DMA6 62 /* DMA Channel 6 */ +#define IRQ_DMA7 63 /* DMA Channel 7 */ + +#define VT8500_NR_IRQS 64 diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_regs.h b/arch/arm/mach-vt8500/include/mach/vt8500_regs.h new file mode 100644 index 000000000000..29c63ecb2383 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/vt8500_regs.h @@ -0,0 +1,79 @@ +/* + * arch/arm/mach-vt8500/include/mach/vt8500_regs.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 __ASM_ARM_ARCH_VT8500_REGS_H +#define __ASM_ARM_ARCH_VT8500_REGS_H + +/* VT8500 Registers Map */ + +#define VT8500_REGS_START_PHYS 0xd8000000 /* Start of MMIO registers */ +#define VT8500_REGS_START_VIRT 0xf8000000 /* Virtual mapping start */ + +#define VT8500_DDR_BASE 0xd8000000 /* 1k DDR/DDR2 Memory + Controller */ +#define VT8500_DMA_BASE 0xd8001000 /* 1k DMA Controller */ +#define VT8500_SFLASH_BASE 0xd8002000 /* 1k Serial Flash Memory + Controller */ +#define VT8500_ETHER_BASE 0xd8004000 /* 1k Ethernet MAC 0 */ +#define VT8500_CIPHER_BASE 0xd8006000 /* 4k Cipher */ +#define VT8500_USB_BASE 0xd8007800 /* 2k USB OTG */ +# define VT8500_EHCI_BASE 0xd8007900 /* EHCI */ +# define VT8500_UHCI_BASE 0xd8007b01 /* UHCI */ +#define VT8500_PATA_BASE 0xd8008000 /* 512 PATA */ +#define VT8500_PS2_BASE 0xd8008800 /* 1k PS/2 */ +#define VT8500_NAND_BASE 0xd8009000 /* 1k NAND Controller */ +#define VT8500_NOR_BASE 0xd8009400 /* 1k NOR Controller */ +#define VT8500_SDMMC_BASE 0xd800a000 /* 1k SD/MMC Controller */ +#define VT8500_MS_BASE 0xd800b000 /* 1k MS/MSPRO Controller */ +#define VT8500_LCDC_BASE 0xd800e400 /* 1k LCD Controller */ +#define VT8500_VPU_BASE 0xd8050000 /* 256 VPU */ +#define VT8500_GOV_BASE 0xd8050300 /* 256 GOV */ +#define VT8500_GEGEA_BASE 0xd8050400 /* 768 GE/GE Alpha Mixing */ +#define VT8500_LCDF_BASE 0xd8050900 /* 256 LCD Formatter */ +#define VT8500_VID_BASE 0xd8050a00 /* 256 VID */ +#define VT8500_VPP_BASE 0xd8050b00 /* 256 VPP */ +#define VT8500_TSBK_BASE 0xd80f4000 /* 4k TSBK */ +#define VT8500_JPEGDEC_BASE 0xd80fe000 /* 4k JPEG Decoder */ +#define VT8500_JPEGENC_BASE 0xd80ff000 /* 4k JPEG Encoder */ +#define VT8500_RTC_BASE 0xd8100000 /* 64k RTC */ +#define VT8500_GPIO_BASE 0xd8110000 /* 64k GPIO Configuration */ +#define VT8500_SCC_BASE 0xd8120000 /* 64k System Configuration*/ +#define VT8500_PMC_BASE 0xd8130000 /* 64k PMC Configuration */ +#define VT8500_IC_BASE 0xd8140000 /* 64k Interrupt Controller*/ +#define VT8500_UART0_BASE 0xd8200000 /* 64k UART 0 */ +#define VT8500_UART2_BASE 0xd8210000 /* 64k UART 2 */ +#define VT8500_PWM_BASE 0xd8220000 /* 64k PWM Configuration */ +#define VT8500_SPI0_BASE 0xd8240000 /* 64k SPI 0 */ +#define VT8500_SPI1_BASE 0xd8250000 /* 64k SPI 1 */ +#define VT8500_CIR_BASE 0xd8270000 /* 64k CIR */ +#define VT8500_I2C0_BASE 0xd8280000 /* 64k I2C 0 */ +#define VT8500_AC97_BASE 0xd8290000 /* 64k AC97 */ +#define VT8500_SPI2_BASE 0xd82a0000 /* 64k SPI 2 */ +#define VT8500_UART1_BASE 0xd82b0000 /* 64k UART 1 */ +#define VT8500_UART3_BASE 0xd82c0000 /* 64k UART 3 */ +#define VT8500_PCM_BASE 0xd82d0000 /* 64k PCM */ +#define VT8500_I2C1_BASE 0xd8320000 /* 64k I2C 1 */ +#define VT8500_I2S_BASE 0xd8330000 /* 64k I2S */ +#define VT8500_ADC_BASE 0xd8340000 /* 64k ADC */ + +#define VT8500_REGS_END_PHYS 0xd834ffff /* End of MMIO registers */ +#define VT8500_REGS_LENGTH (VT8500_REGS_END_PHYS \ + - VT8500_REGS_START_PHYS + 1) + +#endif diff --git a/arch/arm/mach-vt8500/include/mach/vt8500fb.h b/arch/arm/mach-vt8500/include/mach/vt8500fb.h new file mode 100644 index 000000000000..7f399c370fe0 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/vt8500fb.h @@ -0,0 +1,31 @@ +/* + * VT8500/WM8505 Frame Buffer platform data definitions + * + * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _VT8500FB_H +#define _VT8500FB_H + +#include <linux/fb.h> + +struct vt8500fb_platform_data { + struct fb_videomode mode; + u32 xres_virtual; + u32 yres_virtual; + u32 bpp; + unsigned long video_mem_phys; + void *video_mem_virt; + unsigned long video_mem_len; +}; + +#endif /* _VT8500FB_H */ diff --git a/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h b/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h new file mode 100644 index 000000000000..6128627ac753 --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h @@ -0,0 +1,115 @@ +/* + * arch/arm/mach-vt8500/include/mach/wm8505_irqs.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 + */ + +/* WM8505 Interrupt Sources */ + +#define IRQ_UHCI 0 /* UHC FS (UHCI?) */ +#define IRQ_EHCI 1 /* UHC HS */ +#define IRQ_UDCDMA 2 /* UDC DMA */ + /* Reserved */ +#define IRQ_PS2MOUSE 4 /* PS/2 Mouse */ +#define IRQ_UDC 5 /* UDC */ +#define IRQ_EXT0 6 /* External Interrupt 0 */ +#define IRQ_EXT1 7 /* External Interrupt 1 */ +#define IRQ_KEYPAD 8 /* Keypad */ +#define IRQ_DMA 9 /* DMA Controller */ +#define IRQ_ETHER 10 /* Ethernet MAC */ + /* Reserved */ + /* Reserved */ +#define IRQ_EXT2 13 /* External Interrupt 2 */ +#define IRQ_EXT3 14 /* External Interrupt 3 */ +#define IRQ_EXT4 15 /* External Interrupt 4 */ +#define IRQ_APB 16 /* APB Bridge */ +#define IRQ_DMA0 17 /* DMA Channel 0 */ +#define IRQ_I2C1 18 /* I2C 1 */ +#define IRQ_I2C0 19 /* I2C 0 */ +#define IRQ_SDMMC 20 /* SD/MMC Controller */ +#define IRQ_SDMMC_DMA 21 /* SD/MMC Controller DMA */ +#define IRQ_PMC_WU 22 /* Power Management Controller Wakeup */ +#define IRQ_PS2KBD 23 /* PS/2 Keyboard */ +#define IRQ_SPI0 24 /* SPI 0 */ +#define IRQ_SPI1 25 /* SPI 1 */ +#define IRQ_SPI2 26 /* SPI 2 */ +#define IRQ_DMA1 27 /* DMA Channel 1 */ +#define IRQ_NAND 28 /* NAND Flash Controller */ +#define IRQ_NAND_DMA 29 /* NAND Flash Controller DMA */ +#define IRQ_UART5 30 /* UART 5 */ +#define IRQ_UART4 31 /* UART 4 */ +#define IRQ_UART0 32 /* UART 0 */ +#define IRQ_UART1 33 /* UART 1 */ +#define IRQ_DMA2 34 /* DMA Channel 2 */ +#define IRQ_I2S 35 /* I2S */ +#define IRQ_PMCOS0 36 /* PMC OS Timer 0 */ +#define IRQ_PMCOS1 37 /* PMC OS Timer 1 */ +#define IRQ_PMCOS2 38 /* PMC OS Timer 2 */ +#define IRQ_PMCOS3 39 /* PMC OS Timer 3 */ +#define IRQ_DMA3 40 /* DMA Channel 3 */ +#define IRQ_DMA4 41 /* DMA Channel 4 */ +#define IRQ_AC97 42 /* AC97 Interface */ + /* Reserved */ +#define IRQ_NOR 44 /* NOR Flash Controller */ +#define IRQ_DMA5 45 /* DMA Channel 5 */ +#define IRQ_DMA6 46 /* DMA Channel 6 */ +#define IRQ_UART2 47 /* UART 2 */ +#define IRQ_RTC 48 /* RTC Interrupt */ +#define IRQ_RTCSM 49 /* RTC Second/Minute Update Interrupt */ +#define IRQ_UART3 50 /* UART 3 */ +#define IRQ_DMA7 51 /* DMA Channel 7 */ +#define IRQ_EXT5 52 /* External Interrupt 5 */ +#define IRQ_EXT6 53 /* External Interrupt 6 */ +#define IRQ_EXT7 54 /* External Interrupt 7 */ +#define IRQ_CIR 55 /* CIR */ +#define IRQ_SIC0 56 /* SIC IRQ0 */ +#define IRQ_SIC1 57 /* SIC IRQ1 */ +#define IRQ_SIC2 58 /* SIC IRQ2 */ +#define IRQ_SIC3 59 /* SIC IRQ3 */ +#define IRQ_SIC4 60 /* SIC IRQ4 */ +#define IRQ_SIC5 61 /* SIC IRQ5 */ +#define IRQ_SIC6 62 /* SIC IRQ6 */ +#define IRQ_SIC7 63 /* SIC IRQ7 */ + /* Reserved */ +#define IRQ_JPEGDEC 65 /* JPEG Decoder */ +#define IRQ_SAE 66 /* SAE (?) */ + /* Reserved */ +#define IRQ_VPU 79 /* Video Processing Unit */ +#define IRQ_VPP 80 /* Video Post-Processor */ +#define IRQ_VID 81 /* Video Digital Input Interface */ +#define IRQ_SPU 82 /* SPU (?) */ +#define IRQ_PIP 83 /* PIP Error */ +#define IRQ_GE 84 /* Graphic Engine */ +#define IRQ_GOV 85 /* Graphic Overlay Engine */ +#define IRQ_DVO 86 /* Digital Video Output */ + /* Reserved */ +#define IRQ_DMA8 92 /* DMA Channel 8 */ +#define IRQ_DMA9 93 /* DMA Channel 9 */ +#define IRQ_DMA10 94 /* DMA Channel 10 */ +#define IRQ_DMA11 95 /* DMA Channel 11 */ +#define IRQ_DMA12 96 /* DMA Channel 12 */ +#define IRQ_DMA13 97 /* DMA Channel 13 */ +#define IRQ_DMA14 98 /* DMA Channel 14 */ +#define IRQ_DMA15 99 /* DMA Channel 15 */ + /* Reserved */ +#define IRQ_GOVW 111 /* GOVW (?) */ +#define IRQ_GOVRSDSCD 112 /* GOVR SDSCD (?) */ +#define IRQ_GOVRSDMIF 113 /* GOVR SDMIF (?) */ +#define IRQ_GOVRHDSCD 114 /* GOVR HDSCD (?) */ +#define IRQ_GOVRHDMIF 115 /* GOVR HDMIF (?) */ + +#define WM8505_NR_IRQS 116 diff --git a/arch/arm/mach-vt8500/include/mach/wm8505_regs.h b/arch/arm/mach-vt8500/include/mach/wm8505_regs.h new file mode 100644 index 000000000000..df1550941efb --- /dev/null +++ b/arch/arm/mach-vt8500/include/mach/wm8505_regs.h @@ -0,0 +1,78 @@ +/* + * arch/arm/mach-vt8500/include/mach/wm8505_regs.h + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 __ASM_ARM_ARCH_WM8505_REGS_H +#define __ASM_ARM_ARCH_WM8505_REGS_H + +/* WM8505 Registers Map */ + +#define WM8505_REGS_START_PHYS 0xd8000000 /* Start of MMIO registers */ +#define WM8505_REGS_START_VIRT 0xf8000000 /* Virtual mapping start */ + +#define WM8505_DDR_BASE 0xd8000400 /* 1k DDR/DDR2 Memory + Controller */ +#define WM8505_DMA_BASE 0xd8001800 /* 1k DMA Controller */ +#define WM8505_VDMA_BASE 0xd8001c00 /* 1k VDMA */ +#define WM8505_SFLASH_BASE 0xd8002000 /* 1k Serial Flash Memory + Controller */ +#define WM8505_ETHER_BASE 0xd8004000 /* 1k Ethernet MAC 0 */ +#define WM8505_CIPHER_BASE 0xd8006000 /* 4k Cipher */ +#define WM8505_USB_BASE 0xd8007000 /* 2k USB 2.0 Host */ +# define WM8505_EHCI_BASE 0xd8007100 /* EHCI */ +# define WM8505_UHCI_BASE 0xd8007301 /* UHCI */ +#define WM8505_PS2_BASE 0xd8008800 /* 1k PS/2 */ +#define WM8505_NAND_BASE 0xd8009000 /* 1k NAND Controller */ +#define WM8505_NOR_BASE 0xd8009400 /* 1k NOR Controller */ +#define WM8505_SDMMC_BASE 0xd800a000 /* 1k SD/MMC Controller */ +#define WM8505_VPU_BASE 0xd8050000 /* 256 VPU */ +#define WM8505_GOV_BASE 0xd8050300 /* 256 GOV */ +#define WM8505_GEGEA_BASE 0xd8050400 /* 768 GE/GE Alpha Mixing */ +#define WM8505_GOVR_BASE 0xd8050800 /* 512 GOVR (frambuffer) */ +#define WM8505_VID_BASE 0xd8050a00 /* 256 VID */ +#define WM8505_SCL_BASE 0xd8050d00 /* 256 SCL */ +#define WM8505_VPP_BASE 0xd8050f00 /* 256 VPP */ +#define WM8505_JPEGDEC_BASE 0xd80fe000 /* 4k JPEG Decoder */ +#define WM8505_RTC_BASE 0xd8100000 /* 64k RTC */ +#define WM8505_GPIO_BASE 0xd8110000 /* 64k GPIO Configuration */ +#define WM8505_SCC_BASE 0xd8120000 /* 64k System Configuration*/ +#define WM8505_PMC_BASE 0xd8130000 /* 64k PMC Configuration */ +#define WM8505_IC_BASE 0xd8140000 /* 64k Interrupt Controller*/ +#define WM8505_SIC_BASE 0xd8150000 /* 64k Secondary IC */ +#define WM8505_UART0_BASE 0xd8200000 /* 64k UART 0 */ +#define WM8505_UART2_BASE 0xd8210000 /* 64k UART 2 */ +#define WM8505_PWM_BASE 0xd8220000 /* 64k PWM Configuration */ +#define WM8505_SPI0_BASE 0xd8240000 /* 64k SPI 0 */ +#define WM8505_SPI1_BASE 0xd8250000 /* 64k SPI 1 */ +#define WM8505_KEYPAD_BASE 0xd8260000 /* 64k Keypad control */ +#define WM8505_CIR_BASE 0xd8270000 /* 64k CIR */ +#define WM8505_I2C0_BASE 0xd8280000 /* 64k I2C 0 */ +#define WM8505_AC97_BASE 0xd8290000 /* 64k AC97 */ +#define WM8505_SPI2_BASE 0xd82a0000 /* 64k SPI 2 */ +#define WM8505_UART1_BASE 0xd82b0000 /* 64k UART 1 */ +#define WM8505_UART3_BASE 0xd82c0000 /* 64k UART 3 */ +#define WM8505_I2C1_BASE 0xd8320000 /* 64k I2C 1 */ +#define WM8505_I2S_BASE 0xd8330000 /* 64k I2S */ +#define WM8505_UART4_BASE 0xd8370000 /* 64k UART 4 */ +#define WM8505_UART5_BASE 0xd8380000 /* 64k UART 5 */ + +#define WM8505_REGS_END_PHYS 0xd838ffff /* End of MMIO registers */ +#define WM8505_REGS_LENGTH (WM8505_REGS_END_PHYS \ + - WM8505_REGS_START_PHYS + 1) + +#endif diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c new file mode 100644 index 000000000000..5f4ddde4f02a --- /dev/null +++ b/arch/arm/mach-vt8500/irq.c @@ -0,0 +1,177 @@ +/* + * arch/arm/mach-vt8500/irq.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 + */ + +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/interrupt.h> + +#include <asm/irq.h> + +#include "devices.h" + +#define VT8500_IC_DCTR 0x40 /* Destination control + register, 64*u8 */ +#define VT8500_INT_ENABLE (1 << 3) +#define VT8500_TRIGGER_HIGH (0 << 4) +#define VT8500_TRIGGER_RISING (1 << 4) +#define VT8500_TRIGGER_FALLING (2 << 4) +#define VT8500_EDGE ( VT8500_TRIGGER_RISING \ + | VT8500_TRIGGER_FALLING) +#define VT8500_IC_STATUS 0x80 /* Interrupt status, 2*u32 */ + +static void __iomem *ic_regbase; +static void __iomem *sic_regbase; + +static void vt8500_irq_mask(unsigned int irq) +{ + void __iomem *base = ic_regbase; + u8 edge; + + if (irq >= 64) { + base = sic_regbase; + irq -= 64; + } + edge = readb(base + VT8500_IC_DCTR + irq) & VT8500_EDGE; + if (edge) { + void __iomem *stat_reg = base + VT8500_IC_STATUS + + (irq < 32 ? 0 : 4); + unsigned status = readl(stat_reg); + + status |= (1 << (irq & 0x1f)); + writel(status, stat_reg); + } else { + u8 dctr = readb(base + VT8500_IC_DCTR + irq); + + dctr &= ~VT8500_INT_ENABLE; + writeb(dctr, base + VT8500_IC_DCTR + irq); + } +} + +static void vt8500_irq_unmask(unsigned int irq) +{ + void __iomem *base = ic_regbase; + u8 dctr; + + if (irq >= 64) { + base = sic_regbase; + irq -= 64; + } + dctr = readb(base + VT8500_IC_DCTR + irq); + dctr |= VT8500_INT_ENABLE; + writeb(dctr, base + VT8500_IC_DCTR + irq); +} + +static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + void __iomem *base = ic_regbase; + unsigned int orig_irq = irq; + u8 dctr; + + if (irq >= 64) { + base = sic_regbase; + irq -= 64; + } + + dctr = readb(base + VT8500_IC_DCTR + irq); + dctr &= ~VT8500_EDGE; + + switch (flow_type) { + case IRQF_TRIGGER_LOW: + return -EINVAL; + case IRQF_TRIGGER_HIGH: + dctr |= VT8500_TRIGGER_HIGH; + irq_desc[orig_irq].handle_irq = handle_level_irq; + break; + case IRQF_TRIGGER_FALLING: + dctr |= VT8500_TRIGGER_FALLING; + irq_desc[orig_irq].handle_irq = handle_edge_irq; + break; + case IRQF_TRIGGER_RISING: + dctr |= VT8500_TRIGGER_RISING; + irq_desc[orig_irq].handle_irq = handle_edge_irq; + break; + } + writeb(dctr, base + VT8500_IC_DCTR + irq); + + return 0; +} + +static struct irq_chip vt8500_irq_chip = { + .name = "vt8500", + .ack = vt8500_irq_mask, + .mask = vt8500_irq_mask, + .unmask = vt8500_irq_unmask, + .set_type = vt8500_irq_set_type, +}; + +void __init vt8500_init_irq(void) +{ + unsigned int i; + + ic_regbase = ioremap(wmt_ic_base, SZ_64K); + + if (ic_regbase) { + /* Enable rotating priority for IRQ */ + writel((1 << 6), ic_regbase + 0x20); + writel(0, ic_regbase + 0x24); + + for (i = 0; i < wmt_nr_irqs; i++) { + /* Disable all interrupts and route them to IRQ */ + writeb(0x00, ic_regbase + VT8500_IC_DCTR + i); + + set_irq_chip(i, &vt8500_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + } + } else { + printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n"); + } +} + +void __init wm8505_init_irq(void) +{ + unsigned int i; + + ic_regbase = ioremap(wmt_ic_base, SZ_64K); + sic_regbase = ioremap(wmt_sic_base, SZ_64K); + + if (ic_regbase && sic_regbase) { + /* Enable rotating priority for IRQ */ + writel((1 << 6), ic_regbase + 0x20); + writel(0, ic_regbase + 0x24); + writel((1 << 6), sic_regbase + 0x20); + writel(0, sic_regbase + 0x24); + + for (i = 0; i < wmt_nr_irqs; i++) { + /* Disable all interrupts and route them to IRQ */ + if (i < 64) + writeb(0x00, ic_regbase + VT8500_IC_DCTR + i); + else + writeb(0x00, sic_regbase + VT8500_IC_DCTR + + i - 64); + + set_irq_chip(i, &vt8500_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); + } + } else { + printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n"); + } +} diff --git a/arch/arm/mach-vt8500/pwm.c b/arch/arm/mach-vt8500/pwm.c new file mode 100644 index 000000000000..8ad825e93592 --- /dev/null +++ b/arch/arm/mach-vt8500/pwm.c @@ -0,0 +1,265 @@ +/* + * arch/arm/mach-vt8500/pwm.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/pwm.h> +#include <linux/delay.h> + +#include <asm/div64.h> + +#define VT8500_NR_PWMS 4 + +static DEFINE_MUTEX(pwm_lock); +static LIST_HEAD(pwm_list); + +struct pwm_device { + struct list_head node; + struct platform_device *pdev; + + const char *label; + + void __iomem *regbase; + + unsigned int use_count; + unsigned int pwm_id; +}; + +#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) +static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask) +{ + int loops = msecs_to_loops(10); + while ((readb(reg) & bitmask) && --loops) + cpu_relax(); + + if (unlikely(!loops)) + pr_warning("Waiting for status bits 0x%x to clear timed out\n", + bitmask); +} + +int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +{ + unsigned long long c; + unsigned long period_cycles, prescale, pv, dc; + + if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) + return -EINVAL; + + c = 25000000/2; /* wild guess --- need to implement clocks */ + c = c * period_ns; + do_div(c, 1000000000); + period_cycles = c; + + if (period_cycles < 1) + period_cycles = 1; + prescale = (period_cycles - 1) / 4096; + pv = period_cycles / (prescale + 1) - 1; + if (pv > 4095) + pv = 4095; + + if (prescale > 1023) + return -EINVAL; + + c = (unsigned long long)pv * duty_ns; + do_div(c, period_ns); + dc = c; + + pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 1)); + writel(prescale, pwm->regbase + 0x4 + (pwm->pwm_id << 4)); + + pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 2)); + writel(pv, pwm->regbase + 0x8 + (pwm->pwm_id << 4)); + + pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 3)); + writel(dc, pwm->regbase + 0xc + (pwm->pwm_id << 4)); + + return 0; +} +EXPORT_SYMBOL(pwm_config); + +int pwm_enable(struct pwm_device *pwm) +{ + pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0)); + writel(5, pwm->regbase + (pwm->pwm_id << 4)); + return 0; +} +EXPORT_SYMBOL(pwm_enable); + +void pwm_disable(struct pwm_device *pwm) +{ + pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0)); + writel(0, pwm->regbase + (pwm->pwm_id << 4)); +} +EXPORT_SYMBOL(pwm_disable); + +struct pwm_device *pwm_request(int pwm_id, const char *label) +{ + struct pwm_device *pwm; + int found = 0; + + mutex_lock(&pwm_lock); + + list_for_each_entry(pwm, &pwm_list, node) { + if (pwm->pwm_id == pwm_id) { + found = 1; + break; + } + } + + if (found) { + if (pwm->use_count == 0) { + pwm->use_count++; + pwm->label = label; + } else { + pwm = ERR_PTR(-EBUSY); + } + } else { + pwm = ERR_PTR(-ENOENT); + } + + mutex_unlock(&pwm_lock); + return pwm; +} +EXPORT_SYMBOL(pwm_request); + +void pwm_free(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + + if (pwm->use_count) { + pwm->use_count--; + pwm->label = NULL; + } else { + pr_warning("PWM device already freed\n"); + } + + mutex_unlock(&pwm_lock); +} +EXPORT_SYMBOL(pwm_free); + +static inline void __add_pwm(struct pwm_device *pwm) +{ + mutex_lock(&pwm_lock); + list_add_tail(&pwm->node, &pwm_list); + mutex_unlock(&pwm_lock); +} + +static int __devinit pwm_probe(struct platform_device *pdev) +{ + struct pwm_device *pwms; + struct resource *r; + int ret = 0; + int i; + + pwms = kzalloc(sizeof(struct pwm_device) * VT8500_NR_PWMS, GFP_KERNEL); + if (pwms == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + for (i = 0; i < VT8500_NR_PWMS; i++) { + pwms[i].use_count = 0; + pwms[i].pwm_id = i; + pwms[i].pdev = pdev; + } + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (r == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free; + } + + r = request_mem_region(r->start, resource_size(r), pdev->name); + if (r == NULL) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free; + } + + pwms[0].regbase = ioremap(r->start, resource_size(r)); + if (pwms[0].regbase == NULL) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + for (i = 1; i < VT8500_NR_PWMS; i++) + pwms[i].regbase = pwms[0].regbase; + + for (i = 0; i < VT8500_NR_PWMS; i++) + __add_pwm(&pwms[i]); + + platform_set_drvdata(pdev, pwms); + return 0; + +err_free_mem: + release_mem_region(r->start, resource_size(r)); +err_free: + kfree(pwms); + return ret; +} + +static int __devexit pwm_remove(struct platform_device *pdev) +{ + struct pwm_device *pwms; + struct resource *r; + int i; + + pwms = platform_get_drvdata(pdev); + if (pwms == NULL) + return -ENODEV; + + mutex_lock(&pwm_lock); + + for (i = 0; i < VT8500_NR_PWMS; i++) + list_del(&pwms[i].node); + mutex_unlock(&pwm_lock); + + iounmap(pwms[0].regbase); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(r->start, resource_size(r)); + + kfree(pwms); + return 0; +} + +static struct platform_driver pwm_driver = { + .driver = { + .name = "vt8500-pwm", + .owner = THIS_MODULE, + }, + .probe = pwm_probe, + .remove = __devexit_p(pwm_remove), +}; + +static int __init pwm_init(void) +{ + return platform_driver_register(&pwm_driver); +} +arch_initcall(pwm_init); + +static void __exit pwm_exit(void) +{ + platform_driver_unregister(&pwm_driver); +} +module_exit(pwm_exit); + +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-vt8500/timer.c b/arch/arm/mach-vt8500/timer.c new file mode 100644 index 000000000000..d5376c592ab6 --- /dev/null +++ b/arch/arm/mach-vt8500/timer.c @@ -0,0 +1,155 @@ +/* + * arch/arm/mach-vt8500/timer.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 + */ + +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/delay.h> + +#include <asm/mach/time.h> + +#include "devices.h" + +#define VT8500_TIMER_OFFSET 0x0100 +#define TIMER_MATCH_VAL 0x0000 +#define TIMER_COUNT_VAL 0x0010 +#define TIMER_STATUS_VAL 0x0014 +#define TIMER_IER_VAL 0x001c /* interrupt enable */ +#define TIMER_CTRL_VAL 0x0020 +#define TIMER_AS_VAL 0x0024 /* access status */ +#define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ +#define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ +#define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ +#define VT8500_TIMER_HZ 3000000 + +#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) + +static void __iomem *regbase; + +static cycle_t vt8500_timer_read(struct clocksource *cs) +{ + int loops = msecs_to_loops(10); + writel(3, regbase + TIMER_CTRL_VAL); + while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE) + && --loops) + cpu_relax(); + return readl(regbase + TIMER_COUNT_VAL); +} + +struct clocksource clocksource = { + .name = "vt8500_timer", + .rating = 200, + .read = vt8500_timer_read, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int vt8500_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + int loops = msecs_to_loops(10); + cycle_t alarm = clocksource.read(&clocksource) + cycles; + while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE) + && --loops) + cpu_relax(); + writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL); + + if ((signed)(alarm - clocksource.read(&clocksource)) <= 16) + return -ETIME; + + writel(1, regbase + TIMER_IER_VAL); + + return 0; +} + +static void vt8500_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_PERIODIC: + break; + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + writel(readl(regbase + TIMER_CTRL_VAL) | 1, + regbase + TIMER_CTRL_VAL); + writel(0, regbase + TIMER_IER_VAL); + break; + } +} + +struct clock_event_device clockevent = { + .name = "vt8500_timer", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = vt8500_timer_set_next_event, + .set_mode = vt8500_timer_set_mode, +}; + +static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + writel(0xf, regbase + TIMER_STATUS_VAL); + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +struct irqaction irq = { + .name = "vt8500_timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = vt8500_timer_interrupt, + .dev_id = &clockevent, +}; + +static void __init vt8500_timer_init(void) +{ + regbase = ioremap(wmt_pmc_base + VT8500_TIMER_OFFSET, 0x28); + if (!regbase) + printk(KERN_ERR "vt8500_timer_init: failed to map MMIO registers\n"); + + writel(1, regbase + TIMER_CTRL_VAL); + writel(0xf, regbase + TIMER_STATUS_VAL); + writel(~0, regbase + TIMER_MATCH_VAL); + + if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ)) + printk(KERN_ERR "vt8500_timer_init: clocksource_register failed for %s\n", + clocksource.name); + + clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4); + + /* copy-pasted from mach-msm; no idea */ + clockevent.max_delta_ns = + clockevent_delta2ns(0xf0000000, &clockevent); + clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent); + clockevent.cpumask = cpumask_of(0); + + if (setup_irq(wmt_timer_irq, &irq)) + printk(KERN_ERR "vt8500_timer_init: setup_irq failed for %s\n", + clockevent.name); + clockevents_register_device(&clockevent); +} + +struct sys_timer vt8500_timer = { + .init = vt8500_timer_init +}; diff --git a/arch/arm/mach-vt8500/wm8505_7in.c b/arch/arm/mach-vt8500/wm8505_7in.c new file mode 100644 index 000000000000..e73aadbcafd6 --- /dev/null +++ b/arch/arm/mach-vt8500/wm8505_7in.c @@ -0,0 +1,77 @@ +/* + * arch/arm/mach-vt8500/wm8505_7in.c + * + * Copyright (C) 2010 Alexey Charkov <alchark@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 + */ + +#include <linux/io.h> +#include <linux/pm.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +#include "devices.h" + +static void __iomem *pmc_hiber; + +static struct platform_device *devices[] __initdata = { + &vt8500_device_uart0, + &vt8500_device_ehci, + &vt8500_device_wm8505_fb, + &vt8500_device_ge_rops, + &vt8500_device_pwm, + &vt8500_device_pwmbl, + &vt8500_device_rtc, +}; + +static void vt8500_power_off(void) +{ + local_irq_disable(); + writew(5, pmc_hiber); + asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0)); +} + +void __init wm8505_7in_init(void) +{ +#ifdef CONFIG_FB_WM8505 + void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4); + if (gpio_mux_reg) { + writel(readl(gpio_mux_reg) | 0x80000000, gpio_mux_reg); + iounmap(gpio_mux_reg); + } else { + printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n"); + } +#endif + pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2); + if (pmc_hiber) + pm_power_off = &vt8500_power_off; + else + printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n"); + + wm8505_set_resources(); + platform_add_devices(devices, ARRAY_SIZE(devices)); + vt8500_gpio_init(); +} + +MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook") + .boot_params = 0x00000100, + .reserve = wm8505_reserve_mem, + .map_io = wm8505_map_io, + .init_irq = wm8505_init_irq, + .timer = &vt8500_timer, + .init_machine = wm8505_7in_init, +MACHINE_END diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 808b8329b135..89266382b536 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -652,7 +652,7 @@ config ARM_THUMBEE config SWP_EMULATE bool "Emulate SWP/SWPB instructions" - depends on CPU_V7 + depends on !CPU_USE_DOMAINS && CPU_V7 select HAVE_PROC_CPU if PROC_FS default y if SMP help @@ -853,6 +853,11 @@ config CACHE_XSC3L2 help This option enables the L2 cache on XScale3. +config ARM_L1_CACHE_SHIFT_6 + bool + help + Setting ARM L1 cache line size to 64 Bytes. + config ARM_L1_CACHE_SHIFT int default 6 if ARM_L1_CACHE_SHIFT_6 diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 170c9bb95866..ef59099a5463 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -49,7 +49,13 @@ static inline void cache_wait(void __iomem *reg, unsigned long mask) static inline void cache_sync(void) { void __iomem *base = l2x0_base; + +#ifdef CONFIG_ARM_ERRATA_753970 + /* write to an unmmapped register */ + writel_relaxed(0, base + L2X0_DUMMY_REG); +#else writel_relaxed(0, base + L2X0_CACHE_SYNC); +#endif cache_wait(base + L2X0_CACHE_SYNC, 1); } @@ -67,18 +73,24 @@ static inline void l2x0_inv_line(unsigned long addr) writel_relaxed(addr, base + L2X0_INV_LINE_PA); } -#ifdef CONFIG_PL310_ERRATA_588369 -static void debug_writel(unsigned long val) -{ - extern void omap_smc1(u32 fn, u32 arg); +#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915) - /* - * Texas Instrument secure monitor api to modify the - * PL310 Debug Control Register. - */ - omap_smc1(0x100, val); +#define debug_writel(val) outer_cache.set_debug(val) + +static void l2x0_set_debug(unsigned long val) +{ + writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL); +} +#else +/* Optimised out for non-errata case */ +static inline void debug_writel(unsigned long val) +{ } +#define l2x0_set_debug NULL +#endif + +#ifdef CONFIG_PL310_ERRATA_588369 static inline void l2x0_flush_line(unsigned long addr) { void __iomem *base = l2x0_base; @@ -91,11 +103,6 @@ static inline void l2x0_flush_line(unsigned long addr) } #else -/* Optimised out for non-errata case */ -static inline void debug_writel(unsigned long val) -{ -} - static inline void l2x0_flush_line(unsigned long addr) { void __iomem *base = l2x0_base; @@ -119,9 +126,11 @@ static void l2x0_flush_all(void) /* clean all ways */ spin_lock_irqsave(&l2x0_lock, flags); + debug_writel(0x03); writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); cache_sync(); + debug_writel(0x00); spin_unlock_irqrestore(&l2x0_lock, flags); } @@ -329,6 +338,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) outer_cache.flush_all = l2x0_flush_all; outer_cache.inv_all = l2x0_inv_all; outer_cache.disable = l2x0_disable; + outer_cache.set_debug = l2x0_set_debug; printk(KERN_INFO "%s cache controller enabled\n", type); printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n", diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 5164069ced42..cddd684364da 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -297,6 +297,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc) memblock_reserve(__pa(_stext), _end - _stext); #endif #ifdef CONFIG_BLK_DEV_INITRD + if (phys_initrd_size && + memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) { + pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n", + phys_initrd_start, phys_initrd_size); + phys_initrd_start = phys_initrd_size = 0; + } if (phys_initrd_size) { memblock_reserve(phys_initrd_start, phys_initrd_size); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 3c67e92f7d59..ff7b43b5885a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -827,16 +827,6 @@ static void __init sanity_check_meminfo(void) * rather difficult. */ reason = "with VIPT aliasing cache"; - } else if (is_smp() && tlb_ops_need_broadcast()) { - /* - * kmap_high needs to occasionally flush TLB entries, - * however, if the TLB entries need to be broadcast - * we may deadlock: - * kmap_high(irqs off)->flush_all_zero_pkmaps-> - * flush_tlb_kernel_range->smp_call_function_many - * (must not be called with irqs off) - */ - reason = "without hardware TLB ops broadcasting"; } if (reason) { printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n", diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index bcf748d9f4e2..226e3d8351c2 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -493,6 +493,9 @@ arm1020_processor_functions: .word cpu_arm1020_dcache_clean_area .word cpu_arm1020_switch_mm .word cpu_arm1020_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm1020_processor_functions, . - arm1020_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index ab7ec26657ea..86d9c2cf0bce 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -474,6 +474,9 @@ arm1020e_processor_functions: .word cpu_arm1020e_dcache_clean_area .word cpu_arm1020e_switch_mm .word cpu_arm1020e_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm1020e_processor_functions, . - arm1020e_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 831c5e54e22f..83d3dd34f846 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -457,6 +457,9 @@ arm1022_processor_functions: .word cpu_arm1022_dcache_clean_area .word cpu_arm1022_switch_mm .word cpu_arm1022_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm1022_processor_functions, . - arm1022_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index e3f7e9a166bf..686043ee7281 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -452,6 +452,9 @@ arm1026_processor_functions: .word cpu_arm1026_dcache_clean_area .word cpu_arm1026_switch_mm .word cpu_arm1026_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm1026_processor_functions, . - arm1026_processor_functions .section .rodata diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index 6a7be1863edd..5f79dc4ce3fb 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S @@ -284,6 +284,9 @@ ENTRY(arm6_processor_functions) .word cpu_arm6_dcache_clean_area .word cpu_arm6_switch_mm .word cpu_arm6_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm6_processor_functions, . - arm6_processor_functions /* @@ -301,6 +304,9 @@ ENTRY(arm7_processor_functions) .word cpu_arm7_dcache_clean_area .word cpu_arm7_switch_mm .word cpu_arm7_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm7_processor_functions, . - arm7_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index c285395f44b2..665266da143c 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S @@ -185,6 +185,9 @@ ENTRY(arm720_processor_functions) .word cpu_arm720_dcache_clean_area .word cpu_arm720_switch_mm .word cpu_arm720_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm720_processor_functions, . - arm720_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S index 38b27dcba727..6f9d12effee1 100644 --- a/arch/arm/mm/proc-arm740.S +++ b/arch/arm/mm/proc-arm740.S @@ -130,6 +130,9 @@ ENTRY(arm740_processor_functions) .word cpu_arm740_dcache_clean_area .word cpu_arm740_switch_mm .word 0 @ cpu_*_set_pte + .word 0 + .word 0 + .word 0 .size arm740_processor_functions, . - arm740_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S index 0c9786de20af..e4c165ca6696 100644 --- a/arch/arm/mm/proc-arm7tdmi.S +++ b/arch/arm/mm/proc-arm7tdmi.S @@ -70,6 +70,9 @@ ENTRY(arm7tdmi_processor_functions) .word cpu_arm7tdmi_dcache_clean_area .word cpu_arm7tdmi_switch_mm .word 0 @ cpu_*_set_pte + .word 0 + .word 0 + .word 0 .size arm7tdmi_processor_functions, . - arm7tdmi_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 6109f278a904..219980ec8b6e 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -387,6 +387,40 @@ ENTRY(cpu_arm920_set_pte_ext) #endif mov pc, lr +/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ +.globl cpu_arm920_suspend_size +.equ cpu_arm920_suspend_size, 4 * 3 +#ifdef CONFIG_PM +ENTRY(cpu_arm920_do_suspend) + stmfd sp!, {r4 - r7, lr} + mrc p15, 0, r4, c13, c0, 0 @ PID + mrc p15, 0, r5, c3, c0, 0 @ Domain ID + mrc p15, 0, r6, c2, c0, 0 @ TTB address + mrc p15, 0, r7, c1, c0, 0 @ Control register + stmia r0, {r4 - r7} + ldmfd sp!, {r4 - r7, pc} +ENDPROC(cpu_arm920_do_suspend) + +ENTRY(cpu_arm920_do_resume) + mov ip, #0 + mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs + mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches + ldmia r0, {r4 - r7} + mcr p15, 0, r4, c13, c0, 0 @ PID + mcr p15, 0, r5, c3, c0, 0 @ Domain ID + mcr p15, 0, r6, c2, c0, 0 @ TTB address + mov r0, r7 @ control register + mov r2, r6, lsr #14 @ get TTB0 base + mov r2, r2, lsl #14 + ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE + b cpu_resume_mmu +ENDPROC(cpu_arm920_do_resume) +#else +#define cpu_arm920_do_suspend 0 +#define cpu_arm920_do_resume 0 +#endif + __CPUINIT .type __arm920_setup, #function @@ -432,6 +466,9 @@ arm920_processor_functions: .word cpu_arm920_dcache_clean_area .word cpu_arm920_switch_mm .word cpu_arm920_set_pte_ext + .word cpu_arm920_suspend_size + .word cpu_arm920_do_suspend + .word cpu_arm920_do_resume .size arm920_processor_functions, . - arm920_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index bb2f0f46a5e6..36154b1e792a 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -436,6 +436,9 @@ arm922_processor_functions: .word cpu_arm922_dcache_clean_area .word cpu_arm922_switch_mm .word cpu_arm922_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm922_processor_functions, . - arm922_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index c13e01accfe2..89c5e0009c4c 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -503,6 +503,9 @@ arm925_processor_functions: .word cpu_arm925_dcache_clean_area .word cpu_arm925_switch_mm .word cpu_arm925_set_pte_ext + .word 0 + .word 0 + .word 0 .size arm925_processor_functions, . - arm925_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 42eb4315740b..6a4bdb2c94a7 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -401,6 +401,40 @@ ENTRY(cpu_arm926_set_pte_ext) #endif mov pc, lr +/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ +.globl cpu_arm926_suspend_size +.equ cpu_arm926_suspend_size, 4 * 3 +#ifdef CONFIG_PM +ENTRY(cpu_arm926_do_suspend) + stmfd sp!, {r4 - r7, lr} + mrc p15, 0, r4, c13, c0, 0 @ PID + mrc p15, 0, r5, c3, c0, 0 @ Domain ID + mrc p15, 0, r6, c2, c0, 0 @ TTB address + mrc p15, 0, r7, c1, c0, 0 @ Control register + stmia r0, {r4 - r7} + ldmfd sp!, {r4 - r7, pc} +ENDPROC(cpu_arm926_do_suspend) + +ENTRY(cpu_arm926_do_resume) + mov ip, #0 + mcr p15, 0, ip, c8, c7, 0 @ invalidate I+D TLBs + mcr p15, 0, ip, c7, c7, 0 @ invalidate I+D caches + ldmia r0, {r4 - r7} + mcr p15, 0, r4, c13, c0, 0 @ PID + mcr p15, 0, r5, c3, c0, 0 @ Domain ID + mcr p15, 0, r6, c2, c0, 0 @ TTB address + mov r0, r7 @ control register + mov r2, r6, lsr #14 @ get TTB0 base + mov r2, r2, lsl #14 + ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE + b cpu_resume_mmu +ENDPROC(cpu_arm926_do_resume) +#else +#define cpu_arm926_do_suspend 0 +#define cpu_arm926_do_resume 0 +#endif + __CPUINIT .type __arm926_setup, #function @@ -456,6 +490,9 @@ arm926_processor_functions: .word cpu_arm926_dcache_clean_area .word cpu_arm926_switch_mm .word cpu_arm926_set_pte_ext + .word cpu_arm926_suspend_size + .word cpu_arm926_do_suspend + .word cpu_arm926_do_resume .size arm926_processor_functions, . - arm926_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index 7b11cdb9935f..26aea3f71c26 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S @@ -363,6 +363,9 @@ ENTRY(arm940_processor_functions) .word cpu_arm940_dcache_clean_area .word cpu_arm940_switch_mm .word 0 @ cpu_*_set_pte + .word 0 + .word 0 + .word 0 .size arm940_processor_functions, . - arm940_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index 1a5bbf080342..8063345406fe 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S @@ -419,6 +419,9 @@ ENTRY(arm946_processor_functions) .word cpu_arm946_dcache_clean_area .word cpu_arm946_switch_mm .word 0 @ cpu_*_set_pte + .word 0 + .word 0 + .word 0 .size arm946_processor_functions, . - arm946_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S index db67e3134d7a..7b7ebd4d096d 100644 --- a/arch/arm/mm/proc-arm9tdmi.S +++ b/arch/arm/mm/proc-arm9tdmi.S @@ -70,6 +70,9 @@ ENTRY(arm9tdmi_processor_functions) .word cpu_arm9tdmi_dcache_clean_area .word cpu_arm9tdmi_switch_mm .word 0 @ cpu_*_set_pte + .word 0 + .word 0 + .word 0 .size arm9tdmi_processor_functions, . - arm9tdmi_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S index 7c9ad621f0e6..fc2a4ae15cf4 100644 --- a/arch/arm/mm/proc-fa526.S +++ b/arch/arm/mm/proc-fa526.S @@ -195,6 +195,9 @@ fa526_processor_functions: .word cpu_fa526_dcache_clean_area .word cpu_fa526_switch_mm .word cpu_fa526_set_pte_ext + .word 0 + .word 0 + .word 0 .size fa526_processor_functions, . - fa526_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index b4597edbff97..d3883eed7a4a 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S @@ -554,6 +554,9 @@ feroceon_processor_functions: .word cpu_feroceon_dcache_clean_area .word cpu_feroceon_switch_mm .word cpu_feroceon_set_pte_ext + .word 0 + .word 0 + .word 0 .size feroceon_processor_functions, . - feroceon_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S index 4458ee6aa713..9d4f2ae63370 100644 --- a/arch/arm/mm/proc-mohawk.S +++ b/arch/arm/mm/proc-mohawk.S @@ -388,6 +388,9 @@ mohawk_processor_functions: .word cpu_mohawk_dcache_clean_area .word cpu_mohawk_switch_mm .word cpu_mohawk_set_pte_ext + .word 0 + .word 0 + .word 0 .size mohawk_processor_functions, . - mohawk_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 5aa8d59c2e85..46f09ed16b98 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -203,6 +203,9 @@ ENTRY(sa110_processor_functions) .word cpu_sa110_dcache_clean_area .word cpu_sa110_switch_mm .word cpu_sa110_set_pte_ext + .word 0 + .word 0 + .word 0 .size sa110_processor_functions, . - sa110_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index 2ac4e6f10713..74483d1977fe 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -169,6 +169,42 @@ ENTRY(cpu_sa1100_set_pte_ext) #endif mov pc, lr +.globl cpu_sa1100_suspend_size +.equ cpu_sa1100_suspend_size, 4*4 +#ifdef CONFIG_PM +ENTRY(cpu_sa1100_do_suspend) + stmfd sp!, {r4 - r7, lr} + mrc p15, 0, r4, c3, c0, 0 @ domain ID + mrc p15, 0, r5, c2, c0, 0 @ translation table base addr + mrc p15, 0, r6, c13, c0, 0 @ PID + mrc p15, 0, r7, c1, c0, 0 @ control reg + stmia r0, {r4 - r7} @ store cp regs + ldmfd sp!, {r4 - r7, pc} +ENDPROC(cpu_sa1100_do_suspend) + +ENTRY(cpu_sa1100_do_resume) + ldmia r0, {r4 - r7} @ load cp regs + mov r1, #0 + mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs + mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache + mcr p15, 0, r1, c9, c0, 0 @ invalidate RB + mcr p15, 0, r1, c9, c0, 5 @ allow user space to use RB + + mcr p15, 0, r4, c3, c0, 0 @ domain ID + mcr p15, 0, r5, c2, c0, 0 @ translation table base addr + mcr p15, 0, r6, c13, c0, 0 @ PID + mov r0, r7 @ control register + mov r2, r5, lsr #14 @ get TTB0 base + mov r2, r2, lsl #14 + ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE + b cpu_resume_mmu +ENDPROC(cpu_sa1100_do_resume) +#else +#define cpu_sa1100_do_suspend 0 +#define cpu_sa1100_do_resume 0 +#endif + __CPUINIT .type __sa1100_setup, #function @@ -218,6 +254,9 @@ ENTRY(sa1100_processor_functions) .word cpu_sa1100_dcache_clean_area .word cpu_sa1100_switch_mm .word cpu_sa1100_set_pte_ext + .word cpu_sa1100_suspend_size + .word cpu_sa1100_do_suspend + .word cpu_sa1100_do_resume .size sa1100_processor_functions, . - sa1100_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 59a7e1ffe7bc..832b6bdc192c 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -121,6 +121,53 @@ ENTRY(cpu_v6_set_pte_ext) #endif mov pc, lr +/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */ +.globl cpu_v6_suspend_size +.equ cpu_v6_suspend_size, 4 * 8 +#ifdef CONFIG_PM +ENTRY(cpu_v6_do_suspend) + stmfd sp!, {r4 - r11, lr} + mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID + mrc p15, 0, r5, c13, c0, 1 @ Context ID + mrc p15, 0, r6, c3, c0, 0 @ Domain ID + mrc p15, 0, r7, c2, c0, 0 @ Translation table base 0 + mrc p15, 0, r8, c2, c0, 1 @ Translation table base 1 + mrc p15, 0, r9, c1, c0, 1 @ auxillary control register + mrc p15, 0, r10, c1, c0, 2 @ co-processor access control + mrc p15, 0, r11, c1, c0, 0 @ control register + stmia r0, {r4 - r11} + ldmfd sp!, {r4- r11, pc} +ENDPROC(cpu_v6_do_suspend) + +ENTRY(cpu_v6_do_resume) + mov ip, #0 + mcr p15, 0, ip, c7, c14, 0 @ clean+invalidate D cache + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c15, 0 @ clean+invalidate cache + mcr p15, 0, ip, c7, c10, 4 @ drain write buffer + ldmia r0, {r4 - r11} + mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID + mcr p15, 0, r5, c13, c0, 1 @ Context ID + mcr p15, 0, r6, c3, c0, 0 @ Domain ID + mcr p15, 0, r7, c2, c0, 0 @ Translation table base 0 + mcr p15, 0, r8, c2, c0, 1 @ Translation table base 1 + mcr p15, 0, r9, c1, c0, 1 @ auxillary control register + mcr p15, 0, r10, c1, c0, 2 @ co-processor access control + mcr p15, 0, ip, c2, c0, 2 @ TTB control register + mcr p15, 0, ip, c7, c5, 4 @ ISB + mov r0, r11 @ control register + mov r2, r7, lsr #14 @ get TTB0 base + mov r2, r2, lsl #14 + ldr r3, cpu_resume_l1_flags + b cpu_resume_mmu +ENDPROC(cpu_v6_do_resume) +cpu_resume_l1_flags: + ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP) + ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP) +#else +#define cpu_v6_do_suspend 0 +#define cpu_v6_do_resume 0 +#endif .type cpu_v6_name, #object @@ -206,6 +253,9 @@ ENTRY(v6_processor_functions) .word cpu_v6_dcache_clean_area .word cpu_v6_switch_mm .word cpu_v6_set_pte_ext + .word cpu_v6_suspend_size + .word cpu_v6_do_suspend + .word cpu_v6_do_resume .size v6_processor_functions, . - v6_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 0c1172b56b4e..262fa88a7439 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -108,10 +108,16 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_ARM_ERRATA_430973 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB #endif +#ifdef CONFIG_ARM_ERRATA_754322 + dsb +#endif mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID isb 1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 isb +#ifdef CONFIG_ARM_ERRATA_754322 + dsb +#endif mcr p15, 0, r1, c13, c0, 1 @ set context ID isb #endif @@ -171,6 +177,87 @@ cpu_v7_name: .ascii "ARMv7 Processor" .align + /* + * Memory region attributes with SCTLR.TRE=1 + * + * n = TEX[0],C,B + * TR = PRRR[2n+1:2n] - memory type + * IR = NMRR[2n+1:2n] - inner cacheable property + * OR = NMRR[2n+17:2n+16] - outer cacheable property + * + * n TR IR OR + * UNCACHED 000 00 + * BUFFERABLE 001 10 00 00 + * WRITETHROUGH 010 10 10 10 + * WRITEBACK 011 10 11 11 + * reserved 110 + * WRITEALLOC 111 10 01 01 + * DEV_SHARED 100 01 + * DEV_NONSHARED 100 01 + * DEV_WC 001 10 + * DEV_CACHED 011 10 + * + * Other attributes: + * + * DS0 = PRRR[16] = 0 - device shareable property + * DS1 = PRRR[17] = 1 - device shareable property + * NS0 = PRRR[18] = 0 - normal shareable property + * NS1 = PRRR[19] = 1 - normal shareable property + * NOS = PRRR[24+n] = 1 - not outer shareable + */ +.equ PRRR, 0xff0a81a8 +.equ NMRR, 0x40e040e0 + +/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */ +.globl cpu_v7_suspend_size +.equ cpu_v7_suspend_size, 4 * 8 +#ifdef CONFIG_PM +ENTRY(cpu_v7_do_suspend) + stmfd sp!, {r4 - r11, lr} + mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID + mrc p15, 0, r5, c13, c0, 1 @ Context ID + mrc p15, 0, r6, c3, c0, 0 @ Domain ID + mrc p15, 0, r7, c2, c0, 0 @ TTB 0 + mrc p15, 0, r8, c2, c0, 1 @ TTB 1 + mrc p15, 0, r9, c1, c0, 0 @ Control register + mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register + mrc p15, 0, r11, c1, c0, 2 @ Co-processor access control + stmia r0, {r4 - r11} + ldmfd sp!, {r4 - r11, pc} +ENDPROC(cpu_v7_do_suspend) + +ENTRY(cpu_v7_do_resume) + mov ip, #0 + mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + ldmia r0, {r4 - r11} + mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID + mcr p15, 0, r5, c13, c0, 1 @ Context ID + mcr p15, 0, r6, c3, c0, 0 @ Domain ID + mcr p15, 0, r7, c2, c0, 0 @ TTB 0 + mcr p15, 0, r8, c2, c0, 1 @ TTB 1 + mcr p15, 0, ip, c2, c0, 2 @ TTB control register + mcr p15, 0, r10, c1, c0, 1 @ Auxillary control register + mcr p15, 0, r11, c1, c0, 2 @ Co-processor access control + ldr r4, =PRRR @ PRRR + ldr r5, =NMRR @ NMRR + mcr p15, 0, r4, c10, c2, 0 @ write PRRR + mcr p15, 0, r5, c10, c2, 1 @ write NMRR + isb + mov r0, r9 @ control register + mov r2, r7, lsr #14 @ get TTB0 base + mov r2, r2, lsl #14 + ldr r3, cpu_resume_l1_flags + b cpu_resume_mmu +ENDPROC(cpu_v7_do_resume) +cpu_resume_l1_flags: + ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP) + ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP) +#else +#define cpu_v7_do_suspend 0 +#define cpu_v7_do_resume 0 +#endif + __CPUINIT /* @@ -264,6 +351,12 @@ __v7_setup: orreq r10, r10, #1 << 6 @ set bit #6 mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register #endif +#ifdef CONFIG_ARM_ERRATA_751472 + cmp r6, #0x30 @ present prior to r3p0 + mrclt p15, 0, r10, c15, c0, 1 @ read diagnostic register + orrlt r10, r10, #1 << 11 @ set bit #11 + mcrlt p15, 0, r10, c15, c0, 1 @ write diagnostic register +#endif 3: mov r10, #0 #ifdef HARVARD_CACHE @@ -276,36 +369,8 @@ __v7_setup: ALT_SMP(orr r4, r4, #TTB_FLAGS_SMP) ALT_UP(orr r4, r4, #TTB_FLAGS_UP) mcr p15, 0, r4, c2, c0, 1 @ load TTB1 - /* - * Memory region attributes with SCTLR.TRE=1 - * - * n = TEX[0],C,B - * TR = PRRR[2n+1:2n] - memory type - * IR = NMRR[2n+1:2n] - inner cacheable property - * OR = NMRR[2n+17:2n+16] - outer cacheable property - * - * n TR IR OR - * UNCACHED 000 00 - * BUFFERABLE 001 10 00 00 - * WRITETHROUGH 010 10 10 10 - * WRITEBACK 011 10 11 11 - * reserved 110 - * WRITEALLOC 111 10 01 01 - * DEV_SHARED 100 01 - * DEV_NONSHARED 100 01 - * DEV_WC 001 10 - * DEV_CACHED 011 10 - * - * Other attributes: - * - * DS0 = PRRR[16] = 0 - device shareable property - * DS1 = PRRR[17] = 1 - device shareable property - * NS0 = PRRR[18] = 0 - normal shareable property - * NS1 = PRRR[19] = 1 - normal shareable property - * NOS = PRRR[24+n] = 1 - not outer shareable - */ - ldr r5, =0xff0a81a8 @ PRRR - ldr r6, =0x40e040e0 @ NMRR + ldr r5, =PRRR @ PRRR + ldr r6, =NMRR @ NMRR mcr p15, 0, r5, c10, c2, 0 @ write PRRR mcr p15, 0, r6, c10, c2, 1 @ write NMRR #endif @@ -351,6 +416,9 @@ ENTRY(v7_processor_functions) .word cpu_v7_dcache_clean_area .word cpu_v7_switch_mm .word cpu_v7_set_pte_ext + .word 0 + .word 0 + .word 0 .size v7_processor_functions, . - v7_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index ec26355cb7c2..63d8b2044e84 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -413,9 +413,52 @@ ENTRY(cpu_xsc3_set_pte_ext) mov pc, lr .ltorg - .align +.globl cpu_xsc3_suspend_size +.equ cpu_xsc3_suspend_size, 4 * 8 +#ifdef CONFIG_PM +ENTRY(cpu_xsc3_do_suspend) + stmfd sp!, {r4 - r10, lr} + mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode + mrc p15, 0, r5, c15, c1, 0 @ CP access reg + mrc p15, 0, r6, c13, c0, 0 @ PID + mrc p15, 0, r7, c3, c0, 0 @ domain ID + mrc p15, 0, r8, c2, c0, 0 @ translation table base addr + mrc p15, 0, r9, c1, c0, 1 @ auxiliary control reg + mrc p15, 0, r10, c1, c0, 0 @ control reg + bic r4, r4, #2 @ clear frequency change bit + stmia r0, {r1, r4 - r10} @ store v:p offset + cp regs + ldmia sp!, {r4 - r10, pc} +ENDPROC(cpu_xsc3_do_suspend) + +ENTRY(cpu_xsc3_do_resume) + ldmia r0, {r1, r4 - r10} @ load v:p offset + cp regs + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB + mcr p15, 0, ip, c7, c10, 4 @ drain write (&fill) buffer + mcr p15, 0, ip, c7, c5, 4 @ flush prefetch buffer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mcr p14, 0, r4, c6, c0, 0 @ clock configuration, turbo mode. + mcr p15, 0, r5, c15, c1, 0 @ CP access reg + mcr p15, 0, r6, c13, c0, 0 @ PID + mcr p15, 0, r7, c3, c0, 0 @ domain ID + mcr p15, 0, r8, c2, c0, 0 @ translation table base addr + mcr p15, 0, r9, c1, c0, 1 @ auxiliary control reg + + @ temporarily map resume_turn_on_mmu into the page table, + @ otherwise prefetch abort occurs after MMU is turned on + mov r0, r10 @ control register + mov r2, r8, lsr #14 @ get TTB0 base + mov r2, r2, lsl #14 + ldr r3, =0x542e @ section flags + b cpu_resume_mmu +ENDPROC(cpu_xsc3_do_resume) +#else +#define cpu_xsc3_do_suspend 0 +#define cpu_xsc3_do_resume 0 +#endif + __CPUINIT .type __xsc3_setup, #function @@ -476,6 +519,9 @@ ENTRY(xsc3_processor_functions) .word cpu_xsc3_dcache_clean_area .word cpu_xsc3_switch_mm .word cpu_xsc3_set_pte_ext + .word cpu_xsc3_suspend_size + .word cpu_xsc3_do_suspend + .word cpu_xsc3_do_resume .size xsc3_processor_functions, . - xsc3_processor_functions .section ".rodata" diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 5a37c5e45c41..086038cd86ab 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -513,11 +513,49 @@ ENTRY(cpu_xscale_set_pte_ext) xscale_set_pte_ext_epilogue mov pc, lr - .ltorg - .align +.globl cpu_xscale_suspend_size +.equ cpu_xscale_suspend_size, 4 * 7 +#ifdef CONFIG_PM +ENTRY(cpu_xscale_do_suspend) + stmfd sp!, {r4 - r10, lr} + mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode + mrc p15, 0, r5, c15, c1, 0 @ CP access reg + mrc p15, 0, r6, c13, c0, 0 @ PID + mrc p15, 0, r7, c3, c0, 0 @ domain ID + mrc p15, 0, r8, c2, c0, 0 @ translation table base addr + mrc p15, 0, r9, c1, c1, 0 @ auxiliary control reg + mrc p15, 0, r10, c1, c0, 0 @ control reg + bic r4, r4, #2 @ clear frequency change bit + stmia r0, {r4 - r10} @ store cp regs + ldmfd sp!, {r4 - r10, pc} +ENDPROC(cpu_xscale_do_suspend) + +ENTRY(cpu_xscale_do_resume) + ldmia r0, {r4 - r10} @ load cp regs + mov ip, #0 + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mcr p15, 0, ip, c7, c7, 0 @ invalidate I & D caches, BTB + mcr p14, 0, r4, c6, c0, 0 @ clock configuration, turbo mode. + mcr p15, 0, r5, c15, c1, 0 @ CP access reg + mcr p15, 0, r6, c13, c0, 0 @ PID + mcr p15, 0, r7, c3, c0, 0 @ domain ID + mcr p15, 0, r8, c2, c0, 0 @ translation table base addr + mcr p15, 0, r9, c1, c1, 0 @ auxiliary control reg + mov r0, r10 @ control register + mov r2, r8, lsr #14 @ get TTB0 base + mov r2, r2, lsl #14 + ldr r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \ + PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE + b cpu_resume_mmu +ENDPROC(cpu_xscale_do_resume) +#else +#define cpu_xscale_do_suspend 0 +#define cpu_xscale_do_resume 0 +#endif + __CPUINIT .type __xscale_setup, #function @@ -565,6 +603,9 @@ ENTRY(xscale_processor_functions) .word cpu_xscale_dcache_clean_area .word cpu_xscale_switch_mm .word cpu_xscale_set_pte_ext + .word cpu_xscale_suspend_size + .word cpu_xscale_do_suspend + .word cpu_xscale_do_resume .size xscale_processor_functions, . - xscale_processor_functions .section ".rodata" diff --git a/arch/arm/mm/vmregion.c b/arch/arm/mm/vmregion.c index 935993e1b1ef..036fdbfdd62f 100644 --- a/arch/arm/mm/vmregion.c +++ b/arch/arm/mm/vmregion.c @@ -38,7 +38,7 @@ struct arm_vmregion * arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, size_t size, gfp_t gfp) { - unsigned long addr = head->vm_start, end = head->vm_end - size; + unsigned long start = head->vm_start, addr = head->vm_end; unsigned long flags; struct arm_vmregion *c, *new; @@ -54,21 +54,20 @@ arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align, spin_lock_irqsave(&head->vm_lock, flags); - list_for_each_entry(c, &head->vm_list, vm_list) { - if ((addr + size) < addr) - goto nospc; - if ((addr + size) <= c->vm_start) + addr = rounddown(addr - size, align); + list_for_each_entry_reverse(c, &head->vm_list, vm_list) { + if (addr >= c->vm_end) goto found; - addr = ALIGN(c->vm_end, align); - if (addr > end) + addr = rounddown(c->vm_start - size, align); + if (addr < start) goto nospc; } found: /* - * Insert this entry _before_ the one we found. + * Insert this entry after the one we found. */ - list_add_tail(&new->vm_list, &c->vm_list); + list_add(&new->vm_list, &c->vm_list); new->vm_start = addr; new->vm_end = addr + size; new->vm_active = 1; diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index 8aa974491dfc..c074e66ad224 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -10,8 +10,6 @@ */ #include <linux/cpumask.h> -#include <linux/err.h> -#include <linux/errno.h> #include <linux/init.h> #include <linux/mutex.h> #include <linux/oprofile.h> @@ -46,6 +44,7 @@ char *op_name_from_perf_id(void) return NULL; } } +#endif static int report_trace(struct stackframe *frame, void *d) { @@ -85,7 +84,7 @@ static struct frame_tail* user_backtrace(struct frame_tail *tail) /* frame pointers should strictly progress back up the stack * (towards higher addresses) */ - if (tail >= buftail[0].fp) + if (tail + 1 >= buftail[0].fp) return NULL; return buftail[0].fp-1; @@ -111,6 +110,7 @@ static void arm_backtrace(struct pt_regs * const regs, unsigned int depth) int __init oprofile_arch_init(struct oprofile_operations *ops) { + /* provide backtrace support also in timer mode: */ ops->backtrace = arm_backtrace; return oprofile_perf_init(ops); @@ -120,11 +120,3 @@ void __exit oprofile_arch_exit(void) { oprofile_perf_exit(); } -#else -int __init oprofile_arch_init(struct oprofile_operations *ops) -{ - pr_info("oprofile: hardware counters not available\n"); - return -ENODEV; -} -void __exit oprofile_arch_exit(void) {} -#endif /* CONFIG_HW_PERF_EVENTS */ diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h index 3a70ebf0477f..ff469c4f1d76 100644 --- a/arch/arm/plat-mxc/include/mach/uncompress.h +++ b/arch/arm/plat-mxc/include/mach/uncompress.h @@ -95,6 +95,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) case MACH_TYPE_MX35_3DS: case MACH_TYPE_PCM043: case MACH_TYPE_LILLY1131: + case MACH_TYPE_VPR200: uart_base = MX3X_UART1_BASE_ADDR; break; case MACH_TYPE_MAGX_ZN5: @@ -102,6 +103,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) break; case MACH_TYPE_MX51_BABBAGE: case MACH_TYPE_EUKREA_CPUIMX51SD: + case MACH_TYPE_MX51_3DS: uart_base = MX51_UART1_BASE_ADDR; break; case MACH_TYPE_MX50_RDP: diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 18fe3cb195dc..b6333ae3f92a 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -144,12 +144,9 @@ config OMAP_IOMMU_DEBUG config OMAP_IOMMU_IVA2 bool -choice - prompt "System timer" - default OMAP_32K_TIMER if !ARCH_OMAP15XX - config OMAP_MPU_TIMER bool "Use mpu timer" + depends on ARCH_OMAP1 help Select this option if you want to use the OMAP mpu timer. This timer provides more intra-tick resolution than the 32KHz timer, @@ -158,6 +155,7 @@ config OMAP_MPU_TIMER config OMAP_32K_TIMER bool "Use 32KHz timer" depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS + default y if (ARCH_OMAP16XX || ARCH_OMAP2PLUS) help Select this option if you want to enable the OMAP 32KHz timer. This timer saves power compared to the OMAP_MPU_TIMER, and has @@ -165,8 +163,6 @@ config OMAP_32K_TIMER intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is currently only available for OMAP16XX, 24XX, 34XX and OMAP4. -endchoice - config OMAP3_L2_AUX_SECURE_SAVE_RESTORE bool "OMAP3 HS/EMU save and restore for L2 AUX control register" depends on ARCH_OMAP3 && PM diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index ea4644021fb9..862dda95d61d 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -36,8 +36,6 @@ #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 -#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) - #include <linux/clocksource.h> /* @@ -122,12 +120,24 @@ static DEFINE_CLOCK_DATA(cd); #define SC_MULT 4000000000u #define SC_SHIFT 17 -unsigned long long notrace sched_clock(void) +static inline unsigned long long notrace _omap_32k_sched_clock(void) { u32 cyc = clocksource_32k.read(&clocksource_32k); return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); } +#ifndef CONFIG_OMAP_MPU_TIMER +unsigned long long notrace sched_clock(void) +{ + return _omap_32k_sched_clock(); +} +#else +unsigned long long notrace omap_32k_sched_clock(void) +{ + return _omap_32k_sched_clock(); +} +#endif + static void notrace omap_update_sched_clock(void) { u32 cyc = clocksource_32k.read(&clocksource_32k); @@ -160,7 +170,7 @@ void read_persistent_clock(struct timespec *ts) *ts = *tsp; } -static int __init omap_init_clocksource_32k(void) +int __init omap_init_clocksource_32k(void) { static char err[] __initdata = KERN_ERR "%s: can't register clocksource!\n"; @@ -195,7 +205,3 @@ static int __init omap_init_clocksource_32k(void) } return 0; } -arch_initcall(omap_init_clocksource_32k); - -#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */ - diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index c4b2b478b1a5..85363084cc1a 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -53,7 +53,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; #endif #define OMAP_DMA_ACTIVE 0x01 -#define OMAP2_DMA_CSR_CLEAR_MASK 0xffe +#define OMAP2_DMA_CSR_CLEAR_MASK 0xffffffff #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) @@ -1873,7 +1873,7 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA misaligned error with device %d\n", dma_chan[ch].dev_id); - p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); + p->dma_write(status, CSR, ch); p->dma_write(1 << ch, IRQSTATUS_L0, ch); /* read back the register to flush the write */ p->dma_read(IRQSTATUS_L0, ch); @@ -1893,10 +1893,9 @@ static int omap2_dma_handle_ch(int ch) OMAP_DMA_CHAIN_INCQHEAD(chain_id); status = p->dma_read(CSR, ch); + p->dma_write(status, CSR, ch); } - p->dma_write(status, CSR, ch); - if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 6b8088ec74af..29b2afb4288f 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -35,6 +35,9 @@ struct sys_timer; extern void omap_map_common_io(void); extern struct sys_timer omap_timer; +extern bool omap_32k_timer_init(void); +extern int __init omap_init_clocksource_32k(void); +extern unsigned long long notrace omap_32k_sched_clock(void); extern void omap_reserve(void); diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h index 9967d5e855c7..f500fc34d065 100644 --- a/arch/arm/plat-omap/include/plat/sram.h +++ b/arch/arm/plat-omap/include/plat/sram.h @@ -12,7 +12,19 @@ #define __ARCH_ARM_OMAP_SRAM_H #ifndef __ASSEMBLY__ -extern void * omap_sram_push(void * start, unsigned long size); +#include <asm/fncpy.h> + +extern void *omap_sram_push_address(unsigned long size); + +/* Macro to push a function to the internal SRAM, using the fncpy API */ +#define omap_sram_push(funcp, size) ({ \ + typeof(&(funcp)) _res = NULL; \ + void *_sram_address = omap_sram_push_address(size); \ + if (_sram_address) \ + _res = fncpy(_sram_address, &(funcp), size); \ + _res; \ +}) + extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl); extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 459b319a9fad..49d3208793e5 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -322,15 +322,18 @@ static void omap_mbox_fini(struct omap_mbox *mbox) struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) { - struct omap_mbox *mbox; - int ret; + struct omap_mbox *_mbox, *mbox = NULL; + int i, ret; if (!mboxes) return ERR_PTR(-EINVAL); - for (mbox = *mboxes; mbox; mbox++) - if (!strcmp(mbox->name, name)) + for (i = 0; (_mbox = mboxes[i]); i++) { + if (!strcmp(_mbox->name, name)) { + mbox = _mbox; break; + } + } if (!mbox) return ERR_PTR(-ENOENT); diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index e26e50487d60..68fcc7dc56e7 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -242,7 +242,14 @@ static void __init omap_map_sram(void) omap_sram_size - SRAM_BOOTLOADER_SZ); } -void * omap_sram_push(void * start, unsigned long size) +/* + * Memory allocator for SRAM: calculates the new ceiling address + * for pushing a function using the fncpy API. + * + * Note that fncpy requires the returned address to be aligned + * to an 8-byte boundary. + */ +void *omap_sram_push_address(unsigned long size) { if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) { printk(KERN_ERR "Not enough space in SRAM\n"); @@ -250,10 +257,7 @@ void * omap_sram_push(void * start, unsigned long size) } omap_sram_ceil -= size; - omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *)); - memcpy((void *)omap_sram_ceil, start, size); - flush_icache_range((unsigned long)omap_sram_ceil, - (unsigned long)(omap_sram_ceil + size)); + omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN); return (void *)omap_sram_ceil; } diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c index b77e018d36c1..a9aa5ad3f4eb 100644 --- a/arch/arm/plat-pxa/mfp.c +++ b/arch/arm/plat-pxa/mfp.c @@ -139,10 +139,11 @@ static const unsigned long mfpr_edge[] = { #define mfp_configured(p) ((p)->config != -1) /* - * perform a read-back of any MFPR register to make sure the + * perform a read-back of any valid MFPR register to make sure the * previous writings are finished */ -#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) +static unsigned long mfpr_off_readback; +#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + mfpr_off_readback) static inline void __mfp_config_run(struct mfp_pin *p) { @@ -248,6 +249,9 @@ void __init mfp_init_addr(struct mfp_addr_map *map) spin_lock_irqsave(&mfp_spin_lock, flags); + /* mfp offset for readback */ + mfpr_off_readback = map[0].offset; + for (p = map; p->start != MFP_PIN_INVALID; p++) { offset = p->offset; i = p->start; diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S index e73e3b6e88d2..fd7032f84ae7 100644 --- a/arch/arm/plat-s3c24xx/sleep.S +++ b/arch/arm/plat-s3c24xx/sleep.S @@ -44,23 +44,13 @@ /* s3c_cpu_save * * entry: - * r0 = save address (virtual addr of s3c_sleep_save_phys) + * r1 = v:p offset */ ENTRY(s3c_cpu_save) stmfd sp!, { r4 - r12, lr } - - @@ store co-processor registers - - mrc p15, 0, r4, c13, c0, 0 @ PID - mrc p15, 0, r5, c3, c0, 0 @ Domain ID - mrc p15, 0, r6, c2, c0, 0 @ translation table base address - mrc p15, 0, r7, c1, c0, 0 @ control register - - stmia r0, { r4 - r13 } - - @@ write our state back to RAM - bl s3c_pm_cb_flushcache + ldr r3, =resume_with_mmu + bl cpu_suspend @@ jump to final code to send system to sleep ldr r0, =pm_cpu_sleep @@ -76,20 +66,6 @@ resume_with_mmu: .ltorg - @@ the next bits sit in the .data segment, even though they - @@ happen to be code... the s3c_sleep_save_phys needs to be - @@ accessed by the resume code before it can restore the MMU. - @@ This means that the variable has to be close enough for the - @@ code to read it... since the .text segment needs to be RO, - @@ the data segment can be the only place to put this code. - - .data - - .global s3c_sleep_save_phys -s3c_sleep_save_phys: - .word 0 - - /* sleep magic, to allow the bootloader to check for an valid * image to resume to. Must be the first word before the * s3c_cpu_resume entry. @@ -100,10 +76,6 @@ s3c_sleep_save_phys: /* s3c_cpu_resume * * resume code entry for bootloader to call - * - * we must put this code here in the data segment as we have no - * other way of restoring the stack pointer after sleep, and we - * must not write to the code segment (code is read-only) */ ENTRY(s3c_cpu_resume) @@ -134,25 +106,4 @@ ENTRY(s3c_cpu_resume) beq 1001b #endif /* CONFIG_DEBUG_RESUME */ - mov r1, #0 - mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs - mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches - - ldr r0, s3c_sleep_save_phys @ address of restore block - ldmia r0, { r4 - r13 } - - mcr p15, 0, r4, c13, c0, 0 @ PID - mcr p15, 0, r5, c3, c0, 0 @ Domain ID - mcr p15, 0, r6, c2, c0, 0 @ translation table base - -#ifdef CONFIG_DEBUG_RESUME - mov r3, #'R' - strb r3, [ r2, #S3C2410_UTXH ] -#endif - - ldr r2, =resume_with_mmu - mcr p15, 0, r7, c1, c0, 0 @ turn on MMU, etc - nop @ second-to-last before mmu - mov pc, r2 @ go back to virtual address - - .ltorg + b cpu_resume diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index deb39951a22e..557f8c507f6d 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -37,6 +37,14 @@ config S5P_GPIO_INT help Common code for the GPIO interrupts (other than external interrupts.) +comment "System MMU" + +config S5P_SYSTEM_MMU + bool "S5P SYSTEM MMU" + depends on ARCH_S5PV310 + help + Say Y here if you want to enable System MMU + config S5P_DEV_FIMC0 bool help @@ -66,19 +74,3 @@ config S5P_DEV_CSIS1 bool help Compile in platform device definitions for MIPI-CSIS channel 1 - -menuconfig S5P_SYSMMU - bool "SYSMMU support" - depends on ARCH_S5PV310 - help - This is a System MMU driver for Samsung ARM based Soc. - -if S5P_SYSMMU - -config S5P_SYSMMU_DEBUG - bool "Enables debug messages" - depends on S5P_SYSMMU - help - This enables SYSMMU driver debug massages. - -endif diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index 92efe1adcfd6..4bd5cf908977 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -19,6 +19,7 @@ obj-y += clock.o obj-y += irq.o obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o +obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += irq-pm.o @@ -30,4 +31,3 @@ obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o -obj-$(CONFIG_S5P_SYSMMU) += sysmmu.o diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c index 6a7342886171..afaf87fdb93e 100644 --- a/arch/arm/plat-s5p/dev-uart.c +++ b/arch/arm/plat-s5p/dev-uart.c @@ -28,7 +28,7 @@ static struct resource s5p_uart0_resource[] = { [0] = { .start = S5P_PA_UART0, - .end = S5P_PA_UART0 + S5P_SZ_UART, + .end = S5P_PA_UART0 + S5P_SZ_UART - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -51,7 +51,7 @@ static struct resource s5p_uart0_resource[] = { static struct resource s5p_uart1_resource[] = { [0] = { .start = S5P_PA_UART1, - .end = S5P_PA_UART1 + S5P_SZ_UART, + .end = S5P_PA_UART1 + S5P_SZ_UART - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -74,7 +74,7 @@ static struct resource s5p_uart1_resource[] = { static struct resource s5p_uart2_resource[] = { [0] = { .start = S5P_PA_UART2, - .end = S5P_PA_UART2 + S5P_SZ_UART, + .end = S5P_PA_UART2 + S5P_SZ_UART - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -98,7 +98,7 @@ static struct resource s5p_uart3_resource[] = { #if CONFIG_SERIAL_SAMSUNG_UARTS > 3 [0] = { .start = S5P_PA_UART3, - .end = S5P_PA_UART3 + S5P_SZ_UART, + .end = S5P_PA_UART3 + S5P_SZ_UART - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -123,7 +123,7 @@ static struct resource s5p_uart4_resource[] = { #if CONFIG_SERIAL_SAMSUNG_UARTS > 4 [0] = { .start = S5P_PA_UART4, - .end = S5P_PA_UART4 + S5P_SZ_UART, + .end = S5P_PA_UART4 + S5P_SZ_UART - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -148,7 +148,7 @@ static struct resource s5p_uart5_resource[] = { #if CONFIG_SERIAL_SAMSUNG_UARTS > 5 [0] = { .start = S5P_PA_UART5, - .end = S5P_PA_UART5 + S5P_SZ_UART, + .end = S5P_PA_UART5 + S5P_SZ_UART - 1, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/plat-s5p/include/plat/sysmmu.h b/arch/arm/plat-s5p/include/plat/sysmmu.h deleted file mode 100644 index db298fc5438a..000000000000 --- a/arch/arm/plat-s5p/include/plat/sysmmu.h +++ /dev/null @@ -1,23 +0,0 @@ -/* linux/arch/arm/plat-s5p/include/plat/sysmmu.h - * - * Copyright (c) 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Samsung sysmmu driver - * - * 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_PLAT_S5P_SYSMMU_H -#define __ASM_PLAT_S5P_SYSMMU_H __FILE__ - -/* debug macro */ -#ifdef CONFIG_S5P_SYSMMU_DEBUG -#define sysmmu_debug(fmt, arg...) printk(KERN_INFO "[%s] " fmt, __func__, ## arg) -#else -#define sysmmu_debug(fmt, arg...) do { } while (0) -#endif - -#endif /* __ASM_PLAT_S5P_SYSMMU_H */ diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c index d804914dc2e2..ffe8a48bc3c1 100644 --- a/arch/arm/plat-s5p/sysmmu.c +++ b/arch/arm/plat-s5p/sysmmu.c @@ -16,8 +16,6 @@ #include <mach/regs-sysmmu.h> #include <mach/sysmmu.h> -#include <plat/sysmmu.h> - struct sysmmu_controller s5p_sysmmu_cntlrs[S5P_SYSMMU_TOTAL_IPNUM]; void s5p_sysmmu_register(struct sysmmu_controller *sysmmuconp) @@ -123,7 +121,7 @@ static int s5p_sysmmu_set_tablebase(sysmmu_ips ips) : "=r" (pg) : : "cc"); \ pg &= ~0x3fff; - sysmmu_debug("CP15 TTBR0 : 0x%x\n", pg); + printk(KERN_INFO "%s: CP15 TTBR0 : 0x%x\n", __func__, pg); /* Set sysmmu page table base address */ __raw_writel(pg, sysmmuconp->regs + S5P_PT_BASE_ADDR); diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c index 236ef8427d7d..3e4bd8147bf4 100644 --- a/arch/arm/plat-samsung/dev-ts.c +++ b/arch/arm/plat-samsung/dev-ts.c @@ -58,4 +58,3 @@ void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd) s3c_device_ts.dev.platform_data = npd; } -EXPORT_SYMBOL(s3c24xx_ts_set_platdata); diff --git a/arch/arm/plat-samsung/dev-uart.c b/arch/arm/plat-samsung/dev-uart.c index 3776cd952450..5928105490fa 100644 --- a/arch/arm/plat-samsung/dev-uart.c +++ b/arch/arm/plat-samsung/dev-uart.c @@ -15,6 +15,8 @@ #include <linux/kernel.h> #include <linux/platform_device.h> +#include <plat/devs.h> + /* uart devices */ static struct platform_device s3c24xx_uart_device0 = { diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index d9025e377675..937cc2ace517 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -17,6 +17,8 @@ #include <linux/irq.h> +struct sys_device; + #ifdef CONFIG_PM extern __init int s3c_pm_init(void); @@ -50,13 +52,11 @@ extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */ /* from sleep.S */ -extern int s3c_cpu_save(unsigned long *saveblk); +extern int s3c_cpu_save(unsigned long *saveblk, long); extern void s3c_cpu_resume(void); extern void s3c2410_cpu_suspend(void); -extern unsigned long s3c_sleep_save_phys; - /* sleep save info */ /** @@ -179,13 +179,5 @@ extern void s3c_pm_restore_gpios(void); */ extern void s3c_pm_save_gpios(void); -/** - * s3c_pm_cb_flushcache - callback for assembly code - * - * Callback to issue flush_cache_all() as this call is - * not a directly callable object. - */ -extern void s3c_pm_cb_flushcache(void); - extern void s3c_pm_save_core(void); extern void s3c_pm_restore_core(void); diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c index 02d531fb3f81..d5b58d31903c 100644 --- a/arch/arm/plat-samsung/pm.c +++ b/arch/arm/plat-samsung/pm.c @@ -241,8 +241,6 @@ void (*pm_cpu_sleep)(void); static int s3c_pm_enter(suspend_state_t state) { - static unsigned long regs_save[16]; - /* ensure the debug is initialised (if enabled) */ s3c_pm_debug_init(); @@ -266,12 +264,6 @@ static int s3c_pm_enter(suspend_state_t state) return -EINVAL; } - /* store the physical address of the register recovery block */ - - s3c_sleep_save_phys = virt_to_phys(regs_save); - - S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys); - /* save all necessary core registers not covered by the drivers */ s3c_pm_save_gpios(); @@ -305,7 +297,7 @@ static int s3c_pm_enter(suspend_state_t state) * we resume as it saves its own register state and restores it * during the resume. */ - s3c_cpu_save(regs_save); + s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET); /* restore the cpu state using the kernel's cpu init code. */ @@ -336,12 +328,6 @@ static int s3c_pm_enter(suspend_state_t state) return 0; } -/* callback from assembly code */ -void s3c_pm_cb_flushcache(void) -{ - flush_cache_all(); -} - static int s3c_pm_prepare(void) { /* prepare check area if configured */ diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile index eb89540aeda9..b4f340b8f1f1 100644 --- a/arch/arm/plat-spear/Makefile +++ b/arch/arm/plat-spear/Makefile @@ -3,6 +3,6 @@ # # Common support -obj-y := clock.o padmux.o time.o +obj-y := clock.o time.o -obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o +obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o padmux.o diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c index ee4f90e534d8..bdbd7ec9cb6b 100644 --- a/arch/arm/plat-spear/clock.c +++ b/arch/arm/plat-spear/clock.c @@ -12,18 +12,25 @@ */ #include <linux/bug.h> +#include <linux/clk.h> +#include <linux/debugfs.h> #include <linux/err.h> #include <linux/io.h> #include <linux/list.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <mach/misc_regs.h> #include <plat/clock.h> static DEFINE_SPINLOCK(clocks_lock); static LIST_HEAD(root_clks); +#ifdef CONFIG_DEBUG_FS +static LIST_HEAD(clocks); +#endif -static void propagate_rate(struct list_head *); +static void propagate_rate(struct clk *, int on_init); +#ifdef CONFIG_DEBUG_FS +static int clk_debugfs_reparent(struct clk *); +#endif static int generic_clk_enable(struct clk *clk) { @@ -65,6 +72,104 @@ static struct clkops generic_clkops = { .disable = generic_clk_disable, }; +/* returns current programmed clocks clock info structure */ +static struct pclk_info *pclk_info_get(struct clk *clk) +{ + unsigned int val, i; + struct pclk_info *info = NULL; + + val = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift) + & clk->pclk_sel->pclk_sel_mask; + + for (i = 0; i < clk->pclk_sel->pclk_count; i++) { + if (clk->pclk_sel->pclk_info[i].pclk_val == val) + info = &clk->pclk_sel->pclk_info[i]; + } + + return info; +} + +/* + * Set Update pclk, and pclk_info of clk and add clock sibling node to current + * parents children list + */ +static void clk_reparent(struct clk *clk, struct pclk_info *pclk_info) +{ + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + list_del(&clk->sibling); + list_add(&clk->sibling, &pclk_info->pclk->children); + + clk->pclk = pclk_info->pclk; + spin_unlock_irqrestore(&clocks_lock, flags); + +#ifdef CONFIG_DEBUG_FS + clk_debugfs_reparent(clk); +#endif +} + +static void do_clk_disable(struct clk *clk) +{ + if (!clk) + return; + + if (!clk->usage_count) { + WARN_ON(1); + return; + } + + clk->usage_count--; + + if (clk->usage_count == 0) { + /* + * Surely, there are no active childrens or direct users + * of this clock + */ + if (clk->pclk) + do_clk_disable(clk->pclk); + + if (clk->ops && clk->ops->disable) + clk->ops->disable(clk); + } +} + +static int do_clk_enable(struct clk *clk) +{ + int ret = 0; + + if (!clk) + return -EFAULT; + + if (clk->usage_count == 0) { + if (clk->pclk) { + ret = do_clk_enable(clk->pclk); + if (ret) + goto err; + } + if (clk->ops && clk->ops->enable) { + ret = clk->ops->enable(clk); + if (ret) { + if (clk->pclk) + do_clk_disable(clk->pclk); + goto err; + } + } + /* + * Since the clock is going to be used for the first + * time please reclac + */ + if (clk->recalc) { + ret = clk->recalc(clk); + if (ret) + goto err; + } + } + clk->usage_count++; +err: + return ret; +} + /* * clk_enable - inform the system when the clock source should be running. * @clk: clock source @@ -78,17 +183,9 @@ int clk_enable(struct clk *clk) unsigned long flags; int ret = 0; - if (!clk || IS_ERR(clk)) - return -EFAULT; - spin_lock_irqsave(&clocks_lock, flags); - if (clk->usage_count == 0) { - if (clk->ops && clk->ops->enable) - ret = clk->ops->enable(clk); - } - clk->usage_count++; + ret = do_clk_enable(clk); spin_unlock_irqrestore(&clocks_lock, flags); - return ret; } EXPORT_SYMBOL(clk_enable); @@ -109,17 +206,8 @@ void clk_disable(struct clk *clk) { unsigned long flags; - if (!clk || IS_ERR(clk)) - return; - - WARN_ON(clk->usage_count == 0); - spin_lock_irqsave(&clocks_lock, flags); - clk->usage_count--; - if (clk->usage_count == 0) { - if (clk->ops && clk->ops->disable) - clk->ops->disable(clk); - } + do_clk_disable(clk); spin_unlock_irqrestore(&clocks_lock, flags); } EXPORT_SYMBOL(clk_disable); @@ -153,15 +241,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent) int i, found = 0, val = 0; unsigned long flags; - if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent)) + if (!clk || !parent) return -EFAULT; - if (clk->usage_count) - return -EBUSY; - if (!clk->pclk_sel) - return -EPERM; if (clk->pclk == parent) return 0; + if (!clk->pclk_sel) + return -EPERM; + /* check if requested parent is in clk parent list */ for (i = 0; i < clk->pclk_sel->pclk_count; i++) { if (clk->pclk_sel->pclk_info[i].pclk == parent) { found = 1; @@ -176,25 +263,58 @@ int clk_set_parent(struct clk *clk, struct clk *parent) /* reflect parent change in hardware */ val = readl(clk->pclk_sel->pclk_sel_reg); val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift); - val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift; + val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift; writel(val, clk->pclk_sel->pclk_sel_reg); spin_unlock_irqrestore(&clocks_lock, flags); /* reflect parent change in software */ - clk->recalc(clk); - propagate_rate(&clk->children); + clk_reparent(clk, &clk->pclk_sel->pclk_info[i]); + + propagate_rate(clk, 0); return 0; } EXPORT_SYMBOL(clk_set_parent); +/** + * clk_set_rate - set the clock rate for a clock source + * @clk: clock source + * @rate: desired clock rate in Hz + * + * Returns success (0) or negative errno. + */ +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + int ret = -EINVAL; + + if (!clk || !rate) + return -EFAULT; + + if (clk->set_rate) { + spin_lock_irqsave(&clocks_lock, flags); + ret = clk->set_rate(clk, rate); + if (!ret) + /* if successful -> propagate */ + propagate_rate(clk, 0); + spin_unlock_irqrestore(&clocks_lock, flags); + } else if (clk->pclk) { + u32 mult = clk->div_factor ? clk->div_factor : 1; + ret = clk_set_rate(clk->pclk, mult * rate); + } + + return ret; +} +EXPORT_SYMBOL(clk_set_rate); + /* registers clock in platform clock framework */ void clk_register(struct clk_lookup *cl) { - struct clk *clk = cl->clk; + struct clk *clk; unsigned long flags; - if (!clk || IS_ERR(clk)) + if (!cl || !cl->clk) return; + clk = cl->clk; spin_lock_irqsave(&clocks_lock, flags); @@ -207,71 +327,173 @@ void clk_register(struct clk_lookup *cl) /* root clock don't have any parents */ if (!clk->pclk && !clk->pclk_sel) { list_add(&clk->sibling, &root_clks); - /* add clocks with only one parent to parent's children list */ } else if (clk->pclk && !clk->pclk_sel) { + /* add clocks with only one parent to parent's children list */ list_add(&clk->sibling, &clk->pclk->children); } else { - /* add clocks with > 1 parent to 1st parent's children list */ - list_add(&clk->sibling, - &clk->pclk_sel->pclk_info[0].pclk->children); + /* clocks with more than one parent */ + struct pclk_info *pclk_info; + + pclk_info = pclk_info_get(clk); + if (!pclk_info) { + pr_err("CLKDEV: invalid pclk info of clk with" + " %s dev_id and %s con_id\n", + cl->dev_id, cl->con_id); + } else { + clk->pclk = pclk_info->pclk; + list_add(&clk->sibling, &pclk_info->pclk->children); + } } + spin_unlock_irqrestore(&clocks_lock, flags); + /* debugfs specific */ +#ifdef CONFIG_DEBUG_FS + list_add(&clk->node, &clocks); + clk->cl = cl; +#endif + /* add clock to arm clockdev framework */ clkdev_add(cl); } /** - * propagate_rate - recalculate and propagate all clocks in list head + * propagate_rate - recalculate and propagate all clocks to children + * @pclk: parent clock required to be propogated + * @on_init: flag for enabling clocks which are ENABLED_ON_INIT. * - * Recalculates all root clocks in list head, which if the clock's .recalc is - * set correctly, should also propagate their rates. + * Recalculates all children clocks */ -static void propagate_rate(struct list_head *lhead) +void propagate_rate(struct clk *pclk, int on_init) { - struct clk *clkp, *_temp; + struct clk *clk, *_temp; + int ret = 0; - list_for_each_entry_safe(clkp, _temp, lhead, sibling) { - if (clkp->recalc) - clkp->recalc(clkp); - propagate_rate(&clkp->children); + list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) { + if (clk->recalc) { + ret = clk->recalc(clk); + /* + * recalc will return error if clk out is not programmed + * In this case configure default rate. + */ + if (ret && clk->set_rate) + clk->set_rate(clk, 0); + } + propagate_rate(clk, on_init); + + if (!on_init) + continue; + + /* Enable clks enabled on init, in software view */ + if (clk->flags & ENABLED_ON_INIT) + do_clk_enable(clk); } } -/* returns current programmed clocks clock info structure */ -static struct pclk_info *pclk_info_get(struct clk *clk) +/** + * round_rate_index - return closest programmable rate index in rate_config tbl + * @clk: ptr to clock structure + * @drate: desired rate + * @rate: final rate will be returned in this variable only. + * + * Finds index in rate_config for highest clk rate which is less than + * requested rate. If there is no clk rate lesser than requested rate then + * -EINVAL is returned. This routine assumes that rate_config is written + * in incrementing order of clk rates. + * If drate passed is zero then default rate is programmed. + */ +static int +round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate) { - unsigned int mask, i; - unsigned long flags; - struct pclk_info *info = NULL; + unsigned long tmp = 0, prev_rate = 0; + int index; - spin_lock_irqsave(&clocks_lock, flags); - mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift) - & clk->pclk_sel->pclk_sel_mask; + if (!clk->calc_rate) + return -EFAULT; - for (i = 0; i < clk->pclk_sel->pclk_count; i++) { - if (clk->pclk_sel->pclk_info[i].pclk_mask == mask) - info = &clk->pclk_sel->pclk_info[i]; + if (!drate) + return -EINVAL; + + /* + * This loops ends on two conditions: + * - as soon as clk is found with rate greater than requested rate. + * - if all clks in rate_config are smaller than requested rate. + */ + for (index = 0; index < clk->rate_config.count; index++) { + prev_rate = tmp; + tmp = clk->calc_rate(clk, index); + if (drate < tmp) { + index--; + break; + } } - spin_unlock_irqrestore(&clocks_lock, flags); + /* return if can't find suitable clock */ + if (index < 0) { + index = -EINVAL; + *rate = 0; + } else if (index == clk->rate_config.count) { + /* program with highest clk rate possible */ + index = clk->rate_config.count - 1; + *rate = tmp; + } else + *rate = prev_rate; - return info; + return index; } -/* - * Set pclk as cclk's parent and add clock sibling node to current parents - * children list +/** + * clk_round_rate - adjust a rate to the exact rate a clock can provide + * @clk: clock source + * @rate: desired clock rate in Hz + * + * Returns rounded clock rate in Hz, or negative errno. */ -static void change_parent(struct clk *cclk, struct clk *pclk) +long clk_round_rate(struct clk *clk, unsigned long drate) { - unsigned long flags; + long rate = 0; + int index; + + /* + * propagate call to parent who supports calc_rate. Similar approach is + * used in clk_set_rate. + */ + if (!clk->calc_rate) { + u32 mult; + if (!clk->pclk) + return clk->rate; + + mult = clk->div_factor ? clk->div_factor : 1; + return clk_round_rate(clk->pclk, mult * drate) / mult; + } - spin_lock_irqsave(&clocks_lock, flags); - list_del(&cclk->sibling); - list_add(&cclk->sibling, &pclk->children); + index = round_rate_index(clk, drate, &rate); + if (index >= 0) + return rate; + else + return index; +} +EXPORT_SYMBOL(clk_round_rate); - cclk->pclk = pclk; - spin_unlock_irqrestore(&clocks_lock, flags); +/*All below functions are called with lock held */ + +/* + * Calculates pll clk rate for specific value of mode, m, n and p + * + * In normal mode + * rate = (2 * M[15:8] * Fin)/(N * 2^P) + * + * In Dithered mode + * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) + */ +unsigned long pll_calc_rate(struct clk *clk, int index) +{ + unsigned long rate = clk->pclk->rate; + struct pll_rate_tbl *tbls = clk->rate_config.tbls; + unsigned int mode; + + mode = tbls[index].mode ? 256 : 1; + return (((2 * rate / 10000) * tbls[index].m) / + (mode * tbls[index].n * (1 << tbls[index].p))) * 10000; } /* @@ -283,47 +505,146 @@ static void change_parent(struct clk *cclk, struct clk *pclk) * In Dithered mode * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) */ -void pll1_clk_recalc(struct clk *clk) +int pll_clk_recalc(struct clk *clk) { struct pll_clk_config *config = clk->private_data; unsigned int num = 2, den = 0, val, mode = 0; - unsigned long flags; - spin_lock_irqsave(&clocks_lock, flags); - mode = (readl(config->mode_reg) >> PLL_MODE_SHIFT) & - PLL_MODE_MASK; + mode = (readl(config->mode_reg) >> config->masks->mode_shift) & + config->masks->mode_mask; val = readl(config->cfg_reg); /* calculate denominator */ - den = (val >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; + den = (val >> config->masks->div_p_shift) & config->masks->div_p_mask; den = 1 << den; - den *= (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; + den *= (val >> config->masks->div_n_shift) & config->masks->div_n_mask; /* calculate numerator & denominator */ if (!mode) { /* Normal mode */ - num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; + num *= (val >> config->masks->norm_fdbk_m_shift) & + config->masks->norm_fdbk_m_mask; } else { /* Dithered mode */ - num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; + num *= (val >> config->masks->dith_fdbk_m_shift) & + config->masks->dith_fdbk_m_mask; den *= 256; } + if (!den) + return -EINVAL; + clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; - spin_unlock_irqrestore(&clocks_lock, flags); + return 0; +} + +/* + * Configures new clock rate of pll + */ +int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate) +{ + struct pll_rate_tbl *tbls = clk->rate_config.tbls; + struct pll_clk_config *config = clk->private_data; + unsigned long val, rate; + int i; + + i = round_rate_index(clk, desired_rate, &rate); + if (i < 0) + return i; + + val = readl(config->mode_reg) & + ~(config->masks->mode_mask << config->masks->mode_shift); + val |= (tbls[i].mode & config->masks->mode_mask) << + config->masks->mode_shift; + writel(val, config->mode_reg); + + val = readl(config->cfg_reg) & + ~(config->masks->div_p_mask << config->masks->div_p_shift); + val |= (tbls[i].p & config->masks->div_p_mask) << + config->masks->div_p_shift; + val &= ~(config->masks->div_n_mask << config->masks->div_n_shift); + val |= (tbls[i].n & config->masks->div_n_mask) << + config->masks->div_n_shift; + val &= ~(config->masks->dith_fdbk_m_mask << + config->masks->dith_fdbk_m_shift); + if (tbls[i].mode) + val |= (tbls[i].m & config->masks->dith_fdbk_m_mask) << + config->masks->dith_fdbk_m_shift; + else + val |= (tbls[i].m & config->masks->norm_fdbk_m_mask) << + config->masks->norm_fdbk_m_shift; + + writel(val, config->cfg_reg); + + clk->rate = rate; + + return 0; +} + +/* + * Calculates ahb, apb clk rate for specific value of div + */ +unsigned long bus_calc_rate(struct clk *clk, int index) +{ + unsigned long rate = clk->pclk->rate; + struct bus_rate_tbl *tbls = clk->rate_config.tbls; + + return rate / (tbls[index].div + 1); } /* calculates current programmed rate of ahb or apb bus */ -void bus_clk_recalc(struct clk *clk) +int bus_clk_recalc(struct clk *clk) { struct bus_clk_config *config = clk->private_data; unsigned int div; - unsigned long flags; - spin_lock_irqsave(&clocks_lock, flags); - div = ((readl(config->reg) >> config->shift) & config->mask) + 1; + div = ((readl(config->reg) >> config->masks->shift) & + config->masks->mask) + 1; + + if (!div) + return -EINVAL; + clk->rate = (unsigned long)clk->pclk->rate / div; - spin_unlock_irqrestore(&clocks_lock, flags); + return 0; +} + +/* Configures new clock rate of AHB OR APB bus */ +int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate) +{ + struct bus_rate_tbl *tbls = clk->rate_config.tbls; + struct bus_clk_config *config = clk->private_data; + unsigned long val, rate; + int i; + + i = round_rate_index(clk, desired_rate, &rate); + if (i < 0) + return i; + + val = readl(config->reg) & + ~(config->masks->mask << config->masks->shift); + val |= (tbls[i].div & config->masks->mask) << config->masks->shift; + writel(val, config->reg); + + clk->rate = rate; + + return 0; +} + +/* + * gives rate for different values of eq, x and y + * + * Fout from synthesizer can be given from two equations: + * Fout1 = (Fin * X/Y)/2 EQ1 + * Fout2 = Fin * X/Y EQ2 + */ +unsigned long aux_calc_rate(struct clk *clk, int index) +{ + unsigned long rate = clk->pclk->rate; + struct aux_rate_tbl *tbls = clk->rate_config.tbls; + u8 eq = tbls[index].eq ? 1 : 2; + + return (((rate/10000) * tbls[index].xscale) / + (tbls[index].yscale * eq)) * 10000; } /* @@ -336,44 +657,76 @@ void bus_clk_recalc(struct clk *clk) * * Selection of eqn 1 or 2 is programmed in register */ -void aux_clk_recalc(struct clk *clk) +int aux_clk_recalc(struct clk *clk) { struct aux_clk_config *config = clk->private_data; - struct pclk_info *pclk_info = NULL; unsigned int num = 1, den = 1, val, eqn; - unsigned long flags; - /* get current programmed parent */ - pclk_info = pclk_info_get(clk); - if (!pclk_info) { - spin_lock_irqsave(&clocks_lock, flags); - clk->pclk = NULL; - clk->rate = 0; - spin_unlock_irqrestore(&clocks_lock, flags); - return; - } + val = readl(config->synth_reg); - change_parent(clk, pclk_info->pclk); + eqn = (val >> config->masks->eq_sel_shift) & + config->masks->eq_sel_mask; + if (eqn == config->masks->eq1_mask) + den *= 2; - spin_lock_irqsave(&clocks_lock, flags); - if (pclk_info->scalable) { - val = readl(config->synth_reg); + /* calculate numerator */ + num = (val >> config->masks->xscale_sel_shift) & + config->masks->xscale_sel_mask; - eqn = (val >> AUX_EQ_SEL_SHIFT) & AUX_EQ_SEL_MASK; - if (eqn == AUX_EQ1_SEL) - den *= 2; + /* calculate denominator */ + den *= (val >> config->masks->yscale_sel_shift) & + config->masks->yscale_sel_mask; - /* calculate numerator */ - num = (val >> AUX_XSCALE_SHIFT) & AUX_XSCALE_MASK; + if (!den) + return -EINVAL; - /* calculate denominator */ - den *= (val >> AUX_YSCALE_SHIFT) & AUX_YSCALE_MASK; - val = (((clk->pclk->rate/10000) * num) / den) * 10000; - } else - val = clk->pclk->rate; + clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; + return 0; +} - clk->rate = val; - spin_unlock_irqrestore(&clocks_lock, flags); +/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/ +int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate) +{ + struct aux_rate_tbl *tbls = clk->rate_config.tbls; + struct aux_clk_config *config = clk->private_data; + unsigned long val, rate; + int i; + + i = round_rate_index(clk, desired_rate, &rate); + if (i < 0) + return i; + + val = readl(config->synth_reg) & + ~(config->masks->eq_sel_mask << config->masks->eq_sel_shift); + val |= (tbls[i].eq & config->masks->eq_sel_mask) << + config->masks->eq_sel_shift; + val &= ~(config->masks->xscale_sel_mask << + config->masks->xscale_sel_shift); + val |= (tbls[i].xscale & config->masks->xscale_sel_mask) << + config->masks->xscale_sel_shift; + val &= ~(config->masks->yscale_sel_mask << + config->masks->yscale_sel_shift); + val |= (tbls[i].yscale & config->masks->yscale_sel_mask) << + config->masks->yscale_sel_shift; + writel(val, config->synth_reg); + + clk->rate = rate; + + return 0; +} + +/* + * Calculates gpt clk rate for different values of mscale and nscale + * + * Fout= Fin/((2 ^ (N+1)) * (M+1)) + */ +unsigned long gpt_calc_rate(struct clk *clk, int index) +{ + unsigned long rate = clk->pclk->rate; + struct gpt_rate_tbl *tbls = clk->rate_config.tbls; + + return rate / ((1 << (tbls[index].nscale + 1)) * + (tbls[index].mscale + 1)); } /* @@ -381,46 +734,142 @@ void aux_clk_recalc(struct clk *clk) * Fout from synthesizer can be given from below equations: * Fout= Fin/((2 ^ (N+1)) * (M+1)) */ -void gpt_clk_recalc(struct clk *clk) +int gpt_clk_recalc(struct clk *clk) { - struct aux_clk_config *config = clk->private_data; - struct pclk_info *pclk_info = NULL; + struct gpt_clk_config *config = clk->private_data; unsigned int div = 1, val; - unsigned long flags; - pclk_info = pclk_info_get(clk); - if (!pclk_info) { - spin_lock_irqsave(&clocks_lock, flags); - clk->pclk = NULL; - clk->rate = 0; - spin_unlock_irqrestore(&clocks_lock, flags); - return; - } - - change_parent(clk, pclk_info->pclk); + val = readl(config->synth_reg); + div += (val >> config->masks->mscale_sel_shift) & + config->masks->mscale_sel_mask; + div *= 1 << (((val >> config->masks->nscale_sel_shift) & + config->masks->nscale_sel_mask) + 1); - spin_lock_irqsave(&clocks_lock, flags); - if (pclk_info->scalable) { - val = readl(config->synth_reg); - div += (val >> GPT_MSCALE_SHIFT) & GPT_MSCALE_MASK; - div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1); - } + if (!div) + return -EINVAL; clk->rate = (unsigned long)clk->pclk->rate / div; - spin_unlock_irqrestore(&clocks_lock, flags); + return 0; +} + +/* Configures new clock rate of gptiliary synthesizers used by: UART, FIRDA*/ +int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate) +{ + struct gpt_rate_tbl *tbls = clk->rate_config.tbls; + struct gpt_clk_config *config = clk->private_data; + unsigned long val, rate; + int i; + + i = round_rate_index(clk, desired_rate, &rate); + if (i < 0) + return i; + + val = readl(config->synth_reg) & ~(config->masks->mscale_sel_mask << + config->masks->mscale_sel_shift); + val |= (tbls[i].mscale & config->masks->mscale_sel_mask) << + config->masks->mscale_sel_shift; + val &= ~(config->masks->nscale_sel_mask << + config->masks->nscale_sel_shift); + val |= (tbls[i].nscale & config->masks->nscale_sel_mask) << + config->masks->nscale_sel_shift; + writel(val, config->synth_reg); + + clk->rate = rate; + + return 0; } /* - * Used for clocks that always have same value as the parent clock divided by a + * Calculates clcd clk rate for different values of div + * + * Fout from synthesizer can be given from below equation: + * Fout= Fin/2*div (division factor) + * div is 17 bits:- + * 0-13 (fractional part) + * 14-16 (integer part) + * To calculate Fout we left shift val by 14 bits and divide Fin by + * complete div (including fractional part) and then right shift the + * result by 14 places. + */ +unsigned long clcd_calc_rate(struct clk *clk, int index) +{ + unsigned long rate = clk->pclk->rate; + struct clcd_rate_tbl *tbls = clk->rate_config.tbls; + + rate /= 1000; + rate <<= 12; + rate /= (2 * tbls[index].div); + rate >>= 12; + rate *= 1000; + + return rate; +} + +/* + * calculates current programmed rate of clcd synthesizer + * Fout from synthesizer can be given from below equation: + * Fout= Fin/2*div (division factor) + * div is 17 bits:- + * 0-13 (fractional part) + * 14-16 (integer part) + * To calculate Fout we left shift val by 14 bits and divide Fin by + * complete div (including fractional part) and then right shift the + * result by 14 places. + */ +int clcd_clk_recalc(struct clk *clk) +{ + struct clcd_clk_config *config = clk->private_data; + unsigned int div = 1; + unsigned long prate; + unsigned int val; + + val = readl(config->synth_reg); + div = (val >> config->masks->div_factor_shift) & + config->masks->div_factor_mask; + + if (!div) + return -EINVAL; + + prate = clk->pclk->rate / 1000; /* first level division, make it KHz */ + + clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12; + clk->rate *= 1000; + return 0; +} + +/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/ +int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate) +{ + struct clcd_rate_tbl *tbls = clk->rate_config.tbls; + struct clcd_clk_config *config = clk->private_data; + unsigned long val, rate; + int i; + + i = round_rate_index(clk, desired_rate, &rate); + if (i < 0) + return i; + + val = readl(config->synth_reg) & ~(config->masks->div_factor_mask << + config->masks->div_factor_shift); + val |= (tbls[i].div & config->masks->div_factor_mask) << + config->masks->div_factor_shift; + writel(val, config->synth_reg); + + clk->rate = rate; + + return 0; +} + +/* + * Used for clocks that always have value as the parent clock divided by a * fixed divisor */ -void follow_parent(struct clk *clk) +int follow_parent(struct clk *clk) { - unsigned long flags; + unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor; - spin_lock_irqsave(&clocks_lock, flags); - clk->rate = clk->pclk->rate; - spin_unlock_irqrestore(&clocks_lock, flags); + clk->rate = clk->pclk->rate/div_factor; + return 0; } /** @@ -431,5 +880,124 @@ void follow_parent(struct clk *clk) */ void recalc_root_clocks(void) { - propagate_rate(&root_clks); + struct clk *pclk; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&clocks_lock, flags); + list_for_each_entry(pclk, &root_clks, sibling) { + if (pclk->recalc) { + ret = pclk->recalc(pclk); + /* + * recalc will return error if clk out is not programmed + * In this case configure default clock. + */ + if (ret && pclk->set_rate) + pclk->set_rate(pclk, 0); + } + propagate_rate(pclk, 1); + /* Enable clks enabled on init, in software view */ + if (pclk->flags & ENABLED_ON_INIT) + do_clk_enable(pclk); + } + spin_unlock_irqrestore(&clocks_lock, flags); +} + +#ifdef CONFIG_DEBUG_FS +/* + * debugfs support to trace clock tree hierarchy and attributes + */ +static struct dentry *clk_debugfs_root; +static int clk_debugfs_register_one(struct clk *c) +{ + int err; + struct dentry *d, *child; + struct clk *pa = c->pclk; + char s[255]; + char *p = s; + + if (c) { + if (c->cl->con_id) + p += sprintf(p, "%s", c->cl->con_id); + if (c->cl->dev_id) + p += sprintf(p, "%s", c->cl->dev_id); + } + d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root); + if (!d) + return -ENOMEM; + c->dent = d; + + d = debugfs_create_u32("usage_count", S_IRUGO, c->dent, + (u32 *)&c->usage_count); + if (!d) { + err = -ENOMEM; + goto err_out; + } + d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); + if (!d) { + err = -ENOMEM; + goto err_out; + } + d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); + if (!d) { + err = -ENOMEM; + goto err_out; + } + return 0; + +err_out: + d = c->dent; + list_for_each_entry(child, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(c->dent); + return err; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->pclk; + + if (pa && !pa->dent) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (!c->dent) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (!d) + return -ENOMEM; + clk_debugfs_root = d; + + list_for_each_entry(c, &clocks, node) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; +err_out: + debugfs_remove_recursive(clk_debugfs_root); + return err; +} +late_initcall(clk_debugfs_init); + +static int clk_debugfs_reparent(struct clk *c) +{ + debugfs_remove(c->dent); + return clk_debugfs_register_one(c); } +#endif /* CONFIG_DEBUG_FS */ diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h index 2572260f990f..2ae6606930a6 100644 --- a/arch/arm/plat-spear/include/plat/clock.h +++ b/arch/arm/plat-spear/include/plat/clock.h @@ -21,6 +21,7 @@ /* clk structure flags */ #define ALWAYS_ENABLED (1 << 0) /* clock always enabled */ #define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */ +#define ENABLED_ON_INIT (1 << 2) /* clocks enabled at init */ /** * struct clkops - clock operations @@ -35,13 +36,11 @@ struct clkops { /** * struct pclk_info - parents info * @pclk: pointer to parent clk - * @pclk_mask: value to be written for selecting this parent - * @scalable: Is parent scalable (1 - YES, 0 - NO) + * @pclk_val: value to be written for selecting this parent */ struct pclk_info { struct clk *pclk; - u8 pclk_mask; - u8 scalable; + u8 pclk_val; }; /** @@ -54,11 +53,23 @@ struct pclk_info { struct pclk_sel { struct pclk_info *pclk_info; u8 pclk_count; - unsigned int *pclk_sel_reg; + void __iomem *pclk_sel_reg; unsigned int pclk_sel_mask; }; /** + * struct rate_config - clk rate configurations + * @tbls: array of device specific clk rate tables, in ascending order of rates + * @count: size of tbls array + * @default_index: default setting when originally disabled + */ +struct rate_config { + void *tbls; + u8 count; + u8 default_index; +}; + +/** * struct clk - clock structure * @usage_count: num of users who enabled this clock * @flags: flags for clock properties @@ -67,21 +78,32 @@ struct pclk_sel { * @en_reg_bit: clk enable/disable bit * @ops: clk enable/disable ops - generic_clkops selected if NULL * @recalc: pointer to clock rate recalculate function + * @set_rate: pointer to clock set rate function + * @calc_rate: pointer to clock get rate function for index + * @rate_config: rate configuration information, used by set_rate + * @div_factor: division factor to parent clock. * @pclk: current parent clk * @pclk_sel: pointer to parent selection structure * @pclk_sel_shift: register shift for selecting parent of this clock * @children: list for childrens or this clock * @sibling: node for list of clocks having same parents * @private_data: clock specific private data + * @node: list to maintain clocks linearly + * @cl: clocklook up assoicated with this clock + * @dent: object for debugfs */ struct clk { unsigned int usage_count; unsigned int flags; unsigned long rate; - unsigned int *en_reg; + void __iomem *en_reg; u8 en_reg_bit; const struct clkops *ops; - void (*recalc) (struct clk *); + int (*recalc) (struct clk *); + int (*set_rate) (struct clk *, unsigned long rate); + unsigned long (*calc_rate)(struct clk *, int index); + struct rate_config rate_config; + unsigned int div_factor; struct clk *pclk; struct pclk_sel *pclk_sel; @@ -90,37 +112,137 @@ struct clk { struct list_head children; struct list_head sibling; void *private_data; +#ifdef CONFIG_DEBUG_FS + struct list_head node; + struct clk_lookup *cl; + struct dentry *dent; +#endif }; /* pll configuration structure */ +struct pll_clk_masks { + u32 mode_mask; + u32 mode_shift; + + u32 norm_fdbk_m_mask; + u32 norm_fdbk_m_shift; + u32 dith_fdbk_m_mask; + u32 dith_fdbk_m_shift; + u32 div_p_mask; + u32 div_p_shift; + u32 div_n_mask; + u32 div_n_shift; +}; + struct pll_clk_config { - unsigned int *mode_reg; - unsigned int *cfg_reg; + void __iomem *mode_reg; + void __iomem *cfg_reg; + struct pll_clk_masks *masks; +}; + +/* pll clk rate config structure */ +struct pll_rate_tbl { + u8 mode; + u16 m; + u8 n; + u8 p; }; /* ahb and apb bus configuration structure */ +struct bus_clk_masks { + u32 mask; + u32 shift; +}; + struct bus_clk_config { - unsigned int *reg; - unsigned int mask; - unsigned int shift; + void __iomem *reg; + struct bus_clk_masks *masks; +}; + +/* ahb and apb clk bus rate config structure */ +struct bus_rate_tbl { + u8 div; +}; + +/* Aux clk configuration structure: applicable to UART and FIRDA */ +struct aux_clk_masks { + u32 eq_sel_mask; + u32 eq_sel_shift; + u32 eq1_mask; + u32 eq2_mask; + u32 xscale_sel_mask; + u32 xscale_sel_shift; + u32 yscale_sel_mask; + u32 yscale_sel_shift; }; -/* - * Aux clk configuration structure: applicable to GPT, UART and FIRDA - */ struct aux_clk_config { - unsigned int *synth_reg; + void __iomem *synth_reg; + struct aux_clk_masks *masks; +}; + +/* aux clk rate config structure */ +struct aux_rate_tbl { + u16 xscale; + u16 yscale; + u8 eq; +}; + +/* GPT clk configuration structure */ +struct gpt_clk_masks { + u32 mscale_sel_mask; + u32 mscale_sel_shift; + u32 nscale_sel_mask; + u32 nscale_sel_shift; +}; + +struct gpt_clk_config { + void __iomem *synth_reg; + struct gpt_clk_masks *masks; +}; + +/* gpt clk rate config structure */ +struct gpt_rate_tbl { + u16 mscale; + u16 nscale; +}; + +/* clcd clk configuration structure */ +struct clcd_synth_masks { + u32 div_factor_mask; + u32 div_factor_shift; +}; + +struct clcd_clk_config { + void __iomem *synth_reg; + struct clcd_synth_masks *masks; +}; + +/* clcd clk rate config structure */ +struct clcd_rate_tbl { + u16 div; }; /* platform specific clock functions */ void clk_register(struct clk_lookup *cl); void recalc_root_clocks(void); -/* clock recalc functions */ -void follow_parent(struct clk *clk); -void pll1_clk_recalc(struct clk *clk); -void bus_clk_recalc(struct clk *clk); -void gpt_clk_recalc(struct clk *clk); -void aux_clk_recalc(struct clk *clk); +/* clock recalc & set rate functions */ +int follow_parent(struct clk *clk); +unsigned long pll_calc_rate(struct clk *clk, int index); +int pll_clk_recalc(struct clk *clk); +int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate); +unsigned long bus_calc_rate(struct clk *clk, int index); +int bus_clk_recalc(struct clk *clk); +int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate); +unsigned long gpt_calc_rate(struct clk *clk, int index); +int gpt_clk_recalc(struct clk *clk); +int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate); +unsigned long aux_calc_rate(struct clk *clk, int index); +int aux_clk_recalc(struct clk *clk); +int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate); +unsigned long clcd_calc_rate(struct clk *clk, int index); +int clcd_clk_recalc(struct clk *clk); +int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate); #endif /* __PLAT_CLOCK_H */ diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S index e91270e4f640..8501bbf2c092 100644 --- a/arch/arm/plat-spear/include/plat/debug-macro.S +++ b/arch/arm/plat-spear/include/plat/debug-macro.S @@ -12,7 +12,7 @@ */ #include <linux/amba/serial.h> -#include <mach/spear.h> +#include <mach/hardware.h> .macro addruart, rp, rv mov \rp, #SPEAR_DBG_UART_BASE @ Physical base diff --git a/arch/arm/plat-spear/include/plat/hardware.h b/arch/arm/plat-spear/include/plat/hardware.h new file mode 100644 index 000000000000..66d677225d15 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/hardware.h @@ -0,0 +1,23 @@ +/* + * arch/arm/plat-spear/include/plat/hardware.h + * + * Hardware definitions for SPEAr + * + * Copyright (C) 2010 ST Microelectronics + * Viresh Kumar<viresh.kumar@st.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. + */ + +#ifndef __PLAT_HARDWARE_H +#define __PLAT_HARDWARE_H + +#ifndef __ASSEMBLY__ +#define IOMEM(x) ((void __iomem __force *)(x)) +#else +#define IOMEM(x) (x) +#endif + +#endif /* __PLAT_HARDWARE_H */ diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-spear/include/plat/system.h index 55a4e405d578..a235fa0ca777 100644 --- a/arch/arm/plat-spear/include/plat/system.h +++ b/arch/arm/plat-spear/include/plat/system.h @@ -14,9 +14,9 @@ #ifndef __PLAT_SYSTEM_H #define __PLAT_SYSTEM_H -#include <asm/hardware/sp810.h> #include <linux/io.h> -#include <mach/spear.h> +#include <asm/hardware/sp810.h> +#include <mach/hardware.h> static inline void arch_idle(void) { diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h index 99ba6789cc97..1bf84527aee4 100644 --- a/arch/arm/plat-spear/include/plat/uncompress.h +++ b/arch/arm/plat-spear/include/plat/uncompress.h @@ -13,7 +13,7 @@ #include <linux/io.h> #include <linux/amba/serial.h> -#include <mach/spear.h> +#include <mach/hardware.h> #ifndef __PLAT_UNCOMPRESS_H #define __PLAT_UNCOMPRESS_H @@ -24,10 +24,10 @@ static inline void putc(int c) { void __iomem *base = (void __iomem *)SPEAR_DBG_UART_BASE; - while (readl(base + UART01x_FR) & UART01x_FR_TXFF) + while (readl_relaxed(base + UART01x_FR) & UART01x_FR_TXFF) barrier(); - writel(c, base + UART01x_DR); + writel_relaxed(c, base + UART01x_DR); } static inline void flush(void) diff --git a/arch/arm/plat-spear/include/plat/vmalloc.h b/arch/arm/plat-spear/include/plat/vmalloc.h index 09e9372aea21..8c8b24d07046 100644 --- a/arch/arm/plat-spear/include/plat/vmalloc.h +++ b/arch/arm/plat-spear/include/plat/vmalloc.h @@ -14,6 +14,6 @@ #ifndef __PLAT_VMALLOC_H #define __PLAT_VMALLOC_H -#define VMALLOC_END 0xF0000000 +#define VMALLOC_END 0xF0000000UL #endif /* __PLAT_VMALLOC_H */ diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c index 839c88df9994..dbb6e4fff79d 100644 --- a/arch/arm/plat-spear/time.c +++ b/arch/arm/plat-spear/time.c @@ -1,7 +1,7 @@ /* * arch/arm/plat-spear/time.c * - * Copyright (C) 2009 ST Microelectronics + * Copyright (C) 2010 ST Microelectronics * Shiraz Hashim<shiraz.hashim@st.com> * * This file is licensed under the terms of the GNU General Public @@ -20,10 +20,9 @@ #include <linux/time.h> #include <linux/irq.h> #include <asm/mach/time.h> -#include <mach/irqs.h> -#include <mach/hardware.h> -#include <mach/spear.h> #include <mach/generic.h> +#include <mach/hardware.h> +#include <mach/irqs.h> /* * We would use TIMER0 and TIMER1 as clockevent and clocksource. @@ -211,7 +210,7 @@ static void __init spear_clockevent_init(void) void __init spear_setup_timer(void) { - struct clk *pll3_clk; + int ret; if (!request_mem_region(SPEAR_GPT0_BASE, SZ_1K, "gpt0")) { pr_err("%s:cannot get IO addr\n", __func__); @@ -230,26 +229,21 @@ void __init spear_setup_timer(void) goto err_iomap; } - pll3_clk = clk_get(NULL, "pll3_48m_clk"); - if (!pll3_clk) { - pr_err("%s:couldn't get PLL3 as parent for gpt\n", __func__); - goto err_iomap; + ret = clk_enable(gpt_clk); + if (ret < 0) { + pr_err("%s:couldn't enable gpt clock\n", __func__); + goto err_clk; } - clk_set_parent(gpt_clk, pll3_clk); - spear_clockevent_init(); spear_clocksource_init(); return; +err_clk: + clk_put(gpt_clk); err_iomap: iounmap(gpt_base); - err_mem: release_mem_region(SPEAR_GPT0_BASE, SZ_1K); } - -struct sys_timer spear_sys_timer = { - .init = spear_setup_timer, -}; diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types index 2fea897ebeb1..9d6feaabbe7d 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types @@ -12,7 +12,7 @@ # # http://www.arm.linux.org.uk/developer/machines/?action=new # -# Last update: Sun Dec 12 23:24:27 2010 +# Last update: Mon Feb 7 08:59:27 2011 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -2240,7 +2240,7 @@ arm_ultimator2 MACH_ARM_ULTIMATOR2 ARM_ULTIMATOR2 2250 vs_v210 MACH_VS_V210 VS_V210 2252 vs_v212 MACH_VS_V212 VS_V212 2253 hmt MACH_HMT HMT 2254 -suen3 MACH_SUEN3 SUEN3 2255 +km_kirkwood MACH_KM_KIRKWOOD KM_KIRKWOOD 2255 vesper MACH_VESPER VESPER 2256 str9 MACH_STR9 STR9 2257 omap3_wl_ff MACH_OMAP3_WL_FF OMAP3_WL_FF 2258 @@ -2987,7 +2987,7 @@ pxwnas_500_1000 MACH_PXWNAS_500_1000 PXWNAS_500_1000 3001 ea20 MACH_EA20 EA20 3002 awm2 MACH_AWM2 AWM2 3003 ti8148evm MACH_TI8148EVM TI8148EVM 3004 -tegra_seaboard MACH_TEGRA_SEABOARD TEGRA_SEABOARD 3005 +seaboard MACH_SEABOARD SEABOARD 3005 linkstation_chlv2 MACH_LINKSTATION_CHLV2 LINKSTATION_CHLV2 3006 tera_pro2_rack MACH_TERA_PRO2_RACK TERA_PRO2_RACK 3007 rubys MACH_RUBYS RUBYS 3008 @@ -3190,7 +3190,7 @@ synergy MACH_SYNERGY SYNERGY 3205 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 punica MACH_PUNICA PUNICA 3208 -sbc_nt250 MACH_SBC_NT250 SBC_NT250 3209 +trimslice MACH_TRIMSLICE TRIMSLICE 3209 mx27_wmultra MACH_MX27_WMULTRA MX27_WMULTRA 3210 mackerel MACH_MACKEREL MACKEREL 3211 fa9x27 MACH_FA9X27 FA9X27 3213 @@ -3219,3 +3219,100 @@ pivicc MACH_PIVICC PIVICC 3235 pcm048 MACH_PCM048 PCM048 3236 dds MACH_DDS DDS 3237 chalten_xa1 MACH_CHALTEN_XA1 CHALTEN_XA1 3238 +ts48xx MACH_TS48XX TS48XX 3239 +tonga2_tfttimer MACH_TONGA2_TFTTIMER TONGA2_TFTTIMER 3240 +whistler MACH_WHISTLER WHISTLER 3241 +asl_phoenix MACH_ASL_PHOENIX ASL_PHOENIX 3242 +at91sam9263otlite MACH_AT91SAM9263OTLITE AT91SAM9263OTLITE 3243 +ddplug MACH_DDPLUG DDPLUG 3244 +d2plug MACH_D2PLUG D2PLUG 3245 +kzm9d MACH_KZM9D KZM9D 3246 +verdi_lte MACH_VERDI_LTE VERDI_LTE 3247 +nanozoom MACH_NANOZOOM NANOZOOM 3248 +dm3730_som_lv MACH_DM3730_SOM_LV DM3730_SOM_LV 3249 +dm3730_torpedo MACH_DM3730_TORPEDO DM3730_TORPEDO 3250 +anchovy MACH_ANCHOVY ANCHOVY 3251 +re2rev20 MACH_RE2REV20 RE2REV20 3253 +re2rev21 MACH_RE2REV21 RE2REV21 3254 +cns21xx MACH_CNS21XX CNS21XX 3255 +rider MACH_RIDER RIDER 3257 +nsk330 MACH_NSK330 NSK330 3258 +cns2133evb MACH_CNS2133EVB CNS2133EVB 3259 +z3_816x_mod MACH_Z3_816X_MOD Z3_816X_MOD 3260 +z3_814x_mod MACH_Z3_814X_MOD Z3_814X_MOD 3261 +beect MACH_BEECT BEECT 3262 +dma_thunderbug MACH_DMA_THUNDERBUG DMA_THUNDERBUG 3263 +omn_at91sam9g20 MACH_OMN_AT91SAM9G20 OMN_AT91SAM9G20 3264 +mx25_e2s_uc MACH_MX25_E2S_UC MX25_E2S_UC 3265 +mione MACH_MIONE MIONE 3266 +top9000_tcu MACH_TOP9000_TCU TOP9000_TCU 3267 +top9000_bsl MACH_TOP9000_BSL TOP9000_BSL 3268 +kingdom MACH_KINGDOM KINGDOM 3269 +armadillo460 MACH_ARMADILLO460 ARMADILLO460 3270 +lq2 MACH_LQ2 LQ2 3271 +sweda_tms2 MACH_SWEDA_TMS2 SWEDA_TMS2 3272 +mx53_loco MACH_MX53_LOCO MX53_LOCO 3273 +acer_a8 MACH_ACER_A8 ACER_A8 3275 +acer_gauguin MACH_ACER_GAUGUIN ACER_GAUGUIN 3276 +guppy MACH_GUPPY GUPPY 3277 +mx61_ard MACH_MX61_ARD MX61_ARD 3278 +tx53 MACH_TX53 TX53 3279 +omapl138_case_a3 MACH_OMAPL138_CASE_A3 OMAPL138_CASE_A3 3280 +uemd MACH_UEMD UEMD 3281 +ccwmx51mut MACH_CCWMX51MUT CCWMX51MUT 3282 +rockhopper MACH_ROCKHOPPER ROCKHOPPER 3283 +nookcolor MACH_NOOKCOLOR NOOKCOLOR 3284 +hkdkc100 MACH_HKDKC100 HKDKC100 3285 +ts42xx MACH_TS42XX TS42XX 3286 +aebl MACH_AEBL AEBL 3287 +wario MACH_WARIO WARIO 3288 +gfs_spm MACH_GFS_SPM GFS_SPM 3289 +cm_t3730 MACH_CM_T3730 CM_T3730 3290 +isc3 MACH_ISC3 ISC3 3291 +rascal MACH_RASCAL RASCAL 3292 +hrefv60 MACH_HREFV60 HREFV60 3293 +tpt_2_0 MACH_TPT_2_0 TPT_2_0 3294 +pyramid_td MACH_PYRAMID_TD PYRAMID_TD 3295 +splendor MACH_SPLENDOR SPLENDOR 3296 +guf_planet MACH_GUF_PLANET GUF_PLANET 3297 +msm8x60_qt MACH_MSM8X60_QT MSM8X60_QT 3298 +htc_hd_mini MACH_HTC_HD_MINI HTC_HD_MINI 3299 +athene MACH_ATHENE ATHENE 3300 +deep_r_ek_1 MACH_DEEP_R_EK_1 DEEP_R_EK_1 3301 +vivow_ct MACH_VIVOW_CT VIVOW_CT 3302 +nery_1000 MACH_NERY_1000 NERY_1000 3303 +rfl109145_ssrv MACH_RFL109145_SSRV RFL109145_SSRV 3304 +nmh MACH_NMH NMH 3305 +wn802t MACH_WN802T WN802T 3306 +dragonet MACH_DRAGONET DRAGONET 3307 +geneva_b MACH_GENEVA_B GENEVA_B 3308 +at91sam9263desk16l MACH_AT91SAM9263DESK16L AT91SAM9263DESK16L 3309 +bcmhana_sv MACH_BCMHANA_SV BCMHANA_SV 3310 +bcmhana_tablet MACH_BCMHANA_TABLET BCMHANA_TABLET 3311 +koi MACH_KOI KOI 3312 +ts4800 MACH_TS4800 TS4800 3313 +tqma9263 MACH_TQMA9263 TQMA9263 3314 +holiday MACH_HOLIDAY HOLIDAY 3315 +dma_6410 MACH_DMA6410 DMA6410 3316 +pcats_overlay MACH_PCATS_OVERLAY PCATS_OVERLAY 3317 +hwgw6410 MACH_HWGW6410 HWGW6410 3318 +shenzhou MACH_SHENZHOU SHENZHOU 3319 +cwme9210 MACH_CWME9210 CWME9210 3320 +cwme9210js MACH_CWME9210JS CWME9210JS 3321 +pgs_v1 MACH_PGS_SITARA PGS_SITARA 3322 +colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323 +w21 MACH_W21 W21 3324 +polysat1 MACH_POLYSAT1 POLYSAT1 3325 +dataway MACH_DATAWAY DATAWAY 3326 +cobral138 MACH_COBRAL138 COBRAL138 3327 +roverpcs8 MACH_ROVERPCS8 ROVERPCS8 3328 +marvelc MACH_MARVELC MARVELC 3329 +navefihid MACH_NAVEFIHID NAVEFIHID 3330 +dm365_cv100 MACH_DM365_CV100 DM365_CV100 3331 +able MACH_ABLE ABLE 3332 +legacy MACH_LEGACY LEGACY 3333 +icong MACH_ICONG ICONG 3334 +rover_g8 MACH_ROVER_G8 ROVER_G8 3335 +t5388p MACH_T5388P T5388P 3336 +dingo MACH_DINGO DINGO 3337 +goflexhome MACH_GOFLEXHOME GOFLEXHOME 3338 diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 0797cb528b46..bbf3da012afd 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -153,7 +153,7 @@ static struct notifier_block vfp_notifier_block = { * Raise a SIGFPE for the current process. * sicode describes the signal being raised. */ -void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) +static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs) { siginfo_t info; @@ -489,8 +489,11 @@ void vfp_flush_hwstate(struct thread_info *thread) /* * VFP hardware can lose all context when a CPU goes offline. - * Safely clear our held state when a CPU has been killed, and - * re-enable access to VFP when the CPU comes back online. + * As we will be running in SMP mode with CPU hotplug, we will save the + * hardware state at every thread switch. We clear our held state when + * a CPU has been killed, indicating that the VFP hardware doesn't contain + * a threads VFP state. When a CPU starts up, we re-enable access to the + * VFP hardware. * * Both CPU_DYING and CPU_STARTING are called on the CPU which * is being offlined/onlined. |