diff options
295 files changed, 7683 insertions, 3388 deletions
diff --git a/Documentation/arm/SH-Mobile/Makefile b/Documentation/arm/SH-Mobile/Makefile new file mode 100644 index 0000000..8771d83 --- /dev/null +++ b/Documentation/arm/SH-Mobile/Makefile @@ -0,0 +1,8 @@ +BIN := vrl4 + +.PHONY: all +all: $(BIN) + +.PHONY: clean +clean: + rm -f *.o $(BIN) diff --git a/Documentation/arm/SH-Mobile/vrl4.c b/Documentation/arm/SH-Mobile/vrl4.c new file mode 100644 index 0000000..e8a1913 --- /dev/null +++ b/Documentation/arm/SH-Mobile/vrl4.c @@ -0,0 +1,169 @@ +/* + * vrl4 format generator + * + * 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. + */ + +/* + * usage: vrl4 < zImage > out + * dd if=out of=/dev/sdx bs=512 seek=1 # Write the image to sector 1 + * + * Reads a zImage from stdin and writes a vrl4 image to stdout. + * In practice this means writing a padded vrl4 header to stdout followed + * by the zImage. + * + * The padding places the zImage at ALIGN bytes into the output. + * The vrl4 uses ALIGN + START_BASE as the start_address. + * This is where the mask ROM will jump to after verifying the header. + * + * The header sets copy_size to min(sizeof(zImage), MAX_BOOT_PROG_LEN) + ALIGN. + * That is, the mask ROM will load the padded header (ALIGN bytes) + * And then MAX_BOOT_PROG_LEN bytes of the image, or the entire image, + * whichever is smaller. + * + * The zImage is not modified in any way. + */ + +#define _BSD_SOURCE +#include <endian.h> +#include <unistd.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> + +struct hdr { + uint32_t magic1; + uint32_t reserved1; + uint32_t magic2; + uint32_t reserved2; + uint16_t copy_size; + uint16_t boot_options; + uint32_t reserved3; + uint32_t start_address; + uint32_t reserved4; + uint32_t reserved5; + char reserved6[308]; +}; + +#define DECLARE_HDR(h) \ + struct hdr (h) = { \ + .magic1 = htole32(0xea000000), \ + .reserved1 = htole32(0x56), \ + .magic2 = htole32(0xe59ff008), \ + .reserved3 = htole16(0x1) } + +/* Align to 512 bytes, the MMCIF sector size */ +#define ALIGN_BITS 9 +#define ALIGN (1 << ALIGN_BITS) + +#define START_BASE 0xe55b0000 + +/* + * With an alignment of 512 the header uses the first sector. + * There is a 128 sector (64kbyte) limit on the data loaded by the mask ROM. + * So there are 127 sectors left for the boot programme. But in practice + * Only a small portion of a zImage is needed, 16 sectors should be more + * than enough. + * + * Note that this sets how much of the zImage is copied by the mask ROM. + * The entire zImage is present after the header and is loaded + * by the code in the boot program (which is the first portion of the zImage). + */ +#define MAX_BOOT_PROG_LEN (16 * 512) + +#define ROUND_UP(x) ((x + ALIGN - 1) & ~(ALIGN - 1)) + +ssize_t do_read(int fd, void *buf, size_t count) +{ + size_t offset = 0; + ssize_t l; + + while (offset < count) { + l = read(fd, buf + offset, count - offset); + if (!l) + break; + if (l < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + continue; + perror("read"); + return -1; + } + offset += l; + } + + return offset; +} + +ssize_t do_write(int fd, const void *buf, size_t count) +{ + size_t offset = 0; + ssize_t l; + + while (offset < count) { + l = write(fd, buf + offset, count - offset); + if (l < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + continue; + perror("write"); + return -1; + } + offset += l; + } + + return offset; +} + +ssize_t write_zero(int fd, size_t len) +{ + size_t i = len; + + while (i--) { + const char x = 0; + if (do_write(fd, &x, 1) < 0) + return -1; + } + + return len; +} + +int main(void) +{ + DECLARE_HDR(hdr); + char boot_program[MAX_BOOT_PROG_LEN]; + size_t aligned_hdr_len, alligned_prog_len; + ssize_t prog_len; + + prog_len = do_read(0, boot_program, sizeof(boot_program)); + if (prog_len <= 0) + return -1; + + aligned_hdr_len = ROUND_UP(sizeof(hdr)); + hdr.start_address = htole32(START_BASE + aligned_hdr_len); + alligned_prog_len = ROUND_UP(prog_len); + hdr.copy_size = htole16(aligned_hdr_len + alligned_prog_len); + + if (do_write(1, &hdr, sizeof(hdr)) < 0) + return -1; + if (write_zero(1, aligned_hdr_len - sizeof(hdr)) < 0) + return -1; + + if (do_write(1, boot_program, prog_len) < 0) + return 1; + + /* Write out the rest of the kernel */ + while (1) { + prog_len = do_read(0, boot_program, sizeof(boot_program)); + if (prog_len < 0) + return 1; + if (prog_len == 0) + break; + if (do_write(1, boot_program, prog_len) < 0) + return 1; + } + + return 0; +} diff --git a/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt b/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt new file mode 100644 index 0000000..efff8ae --- /dev/null +++ b/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt @@ -0,0 +1,29 @@ +ROM-able zImage boot from MMC +----------------------------- + +An ROM-able zImage compiled with ZBOOT_ROM_MMCIF may be written to MMC and +SuperH Mobile ARM will to boot directly from the MMCIF hardware block. + +This is achieved by the mask ROM loading the first portion of the image into +MERAM and then jumping to it. This portion contains loader code which +copies the entire image to SDRAM and jumps to it. From there the zImage +boot code proceeds as normal, uncompressing the image into its final +location and then jumping to it. + +This code has been tested on an AP4EB board using the developer 1A eMMC +boot mode which is configured using the following jumper settings. +The board used for testing required a patched mask ROM in order for +this mode to function. + + 8 7 6 5 4 3 2 1 + x|x|x|x|x| |x| +S4 -+-+-+-+-+-+-+- + | | | | |x| |x on + +The zImage must be written to the MMC card at sector 1 (512 bytes) in +vrl4 format. A utility vrl4 is supplied to accomplish this. + +e.g. + vrl4 < zImage | dd of=/dev/sdX bs=512 seek=1 + +A dual-voltage MMC 4.0 card was used for testing. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 166efa2..48a0628 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -7,7 +7,7 @@ config ARM select HAVE_MEMBLOCK select RTC_LIB select SYS_SUPPORTS_APM_EMULATION - select GENERIC_ATOMIC64 if (!CPU_32v6K || !AEABI) + select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI) select HAVE_OPROFILE if (HAVE_PERF_EVENTS) select HAVE_ARCH_KGDB select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL) @@ -24,7 +24,7 @@ config ARM select HAVE_PERF_EVENTS select PERF_USE_VMALLOC select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7)) + select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)) select HAVE_C_RECORDMCOUNT select HAVE_GENERIC_HARDIRQS select HAVE_SPARSE_IRQ @@ -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 @@ -191,6 +190,22 @@ config VECTORS_BASE help The base address of exception vectors. +config ARM_PATCH_PHYS_VIRT + bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on !XIP_KERNEL && MMU + depends on !ARCH_REALVIEW || !SPARSEMEM + help + Patch phys-to-virt translation functions at runtime according to + the position of the kernel in system memory. + + This can only be used with non-XIP with MMU kernels where + the base of physical memory is at a 16MB boundary. + +config ARM_PATCH_PHYS_VIRT_16BIT + def_bool y + depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM + source "init/Kconfig" source "kernel/Kconfig.freezer" @@ -346,7 +361,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. @@ -457,6 +472,7 @@ config ARCH_IXP4XX config ARCH_DOVE bool "Marvell Dove" + select CPU_V6K select PCI select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS @@ -875,6 +891,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 # @@ -1007,6 +1033,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 @@ -1048,7 +1076,7 @@ config XSCALE_PMU default y config CPU_HAS_PMU - depends on (CPU_V6 || CPU_V7 || XSCALE_PMU) && \ + depends on (CPU_V6 || CPU_V6K || CPU_V7 || XSCALE_PMU) && \ (!ARCH_OMAP3 || OMAP3_EMU) default y bool @@ -1064,7 +1092,7 @@ endif config ARM_ERRATA_411920 bool "ARM errata: Invalidation of the Instruction Cache operation can fail" - depends on CPU_V6 + depends on CPU_V6 || CPU_V6K help Invalidation of the Instruction Cache operation can fail. This erratum is present in 1136 (before r1p4), 1156 and 1176. @@ -1140,7 +1168,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 @@ -1149,8 +1177,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" @@ -1164,6 +1191,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 @@ -1202,6 +1240,28 @@ config ARM_ERRATA_753970 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" @@ -1275,6 +1335,7 @@ source "kernel/time/Kconfig" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" depends on EXPERIMENTAL + depends on CPU_V6K || CPU_V7 depends on GENERIC_CLOCKEVENTS depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \ MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \ @@ -1386,7 +1447,7 @@ config HZ config THUMB2_KERNEL bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)" - depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL + depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL select AEABI select ARM_ASM_UNIFIED help @@ -1396,6 +1457,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 @@ -1644,6 +1736,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 "" @@ -1877,7 +1981,7 @@ config FPE_FASTFPE config VFP bool "VFP-format floating point maths" - depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON + depends on CPU_V6 || CPU_V6K || CPU_ARM926T || CPU_V7 || CPU_FEROCEON help Say Y to include VFP support code in the kernel. This is needed if your hardware includes a VFP unit. diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 6f7b292..1e20c41 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -89,6 +89,7 @@ tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale tune-$(CONFIG_CPU_FEROCEON) :=$(call cc-option,-mtune=marvell-f,-mtune=xscale) tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) +tune-$(CONFIG_CPU_V6K) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) ifeq ($(CONFIG_AEABI),y) CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork @@ -105,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 @@ -190,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 @@ -280,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 @@ -301,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 4d26f2c..9128fdd 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/Makefile b/arch/arm/boot/compressed/Makefile index 0a8f748..f9f77c6 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 30973b7..c943d2e 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 0000000..1dc1e21 --- /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 7193884..84ac4d6 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -21,7 +21,7 @@ #if defined(CONFIG_DEBUG_ICEDCC) -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) .macro loadsp, rb, tmp .endm .macro writeb, ch, rb @@ -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/misc.c b/arch/arm/boot/compressed/misc.c index e653a6d..4657e87 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -36,7 +36,7 @@ extern void error(char *x); #ifdef CONFIG_DEBUG_ICEDCC -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) static void icedcc_putc(int ch) { diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c new file mode 100644 index 0000000..e6180af --- /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 366a924..5309909 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/gic.c b/arch/arm/common/gic.c index 2243772..cb6b041 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 93d04ac..92f10cb 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/bitops.h b/arch/arm/include/asm/bitops.h index 7b1bb2b..af54ed1 100644 --- a/arch/arm/include/asm/bitops.h +++ b/arch/arm/include/asm/bitops.h @@ -149,14 +149,18 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p) */ /* + * Native endian assembly bitops. nr = 0 -> word 0 bit 0. + */ +extern void _set_bit(int nr, volatile unsigned long * p); +extern void _clear_bit(int nr, volatile unsigned long * p); +extern void _change_bit(int nr, volatile unsigned long * p); +extern int _test_and_set_bit(int nr, volatile unsigned long * p); +extern int _test_and_clear_bit(int nr, volatile unsigned long * p); +extern int _test_and_change_bit(int nr, volatile unsigned long * p); + +/* * Little endian assembly bitops. nr = 0 -> byte 0 bit 0. */ -extern void _set_bit_le(int nr, volatile unsigned long * p); -extern void _clear_bit_le(int nr, volatile unsigned long * p); -extern void _change_bit_le(int nr, volatile unsigned long * p); -extern int _test_and_set_bit_le(int nr, volatile unsigned long * p); -extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p); -extern int _test_and_change_bit_le(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_le(const void * p, unsigned size); extern int _find_next_zero_bit_le(const void * p, int size, int offset); extern int _find_first_bit_le(const unsigned long *p, unsigned size); @@ -165,12 +169,6 @@ extern int _find_next_bit_le(const unsigned long *p, int size, int offset); /* * Big endian assembly bitops. nr = 0 -> byte 3 bit 0. */ -extern void _set_bit_be(int nr, volatile unsigned long * p); -extern void _clear_bit_be(int nr, volatile unsigned long * p); -extern void _change_bit_be(int nr, volatile unsigned long * p); -extern int _test_and_set_bit_be(int nr, volatile unsigned long * p); -extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p); -extern int _test_and_change_bit_be(int nr, volatile unsigned long * p); extern int _find_first_zero_bit_be(const void * p, unsigned size); extern int _find_next_zero_bit_be(const void * p, int size, int offset); extern int _find_first_bit_be(const unsigned long *p, unsigned size); @@ -180,33 +178,26 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); /* * The __* form of bitops are non-atomic and may be reordered. */ -#define ATOMIC_BITOP_LE(name,nr,p) \ - (__builtin_constant_p(nr) ? \ - ____atomic_##name(nr, p) : \ - _##name##_le(nr,p)) - -#define ATOMIC_BITOP_BE(name,nr,p) \ - (__builtin_constant_p(nr) ? \ - ____atomic_##name(nr, p) : \ - _##name##_be(nr,p)) +#define ATOMIC_BITOP(name,nr,p) \ + (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p)) #else -#define ATOMIC_BITOP_LE(name,nr,p) _##name##_le(nr,p) -#define ATOMIC_BITOP_BE(name,nr,p) _##name##_be(nr,p) +#define ATOMIC_BITOP(name,nr,p) _##name(nr,p) #endif -#define NONATOMIC_BITOP(name,nr,p) \ - (____nonatomic_##name(nr, p)) +/* + * Native endian atomic definitions. + */ +#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p) +#define clear_bit(nr,p) ATOMIC_BITOP(clear_bit,nr,p) +#define change_bit(nr,p) ATOMIC_BITOP(change_bit,nr,p) +#define test_and_set_bit(nr,p) ATOMIC_BITOP(test_and_set_bit,nr,p) +#define test_and_clear_bit(nr,p) ATOMIC_BITOP(test_and_clear_bit,nr,p) +#define test_and_change_bit(nr,p) ATOMIC_BITOP(test_and_change_bit,nr,p) #ifndef __ARMEB__ /* * These are the little endian, atomic definitions. */ -#define set_bit(nr,p) ATOMIC_BITOP_LE(set_bit,nr,p) -#define clear_bit(nr,p) ATOMIC_BITOP_LE(clear_bit,nr,p) -#define change_bit(nr,p) ATOMIC_BITOP_LE(change_bit,nr,p) -#define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p) -#define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p) -#define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off) #define find_first_bit(p,sz) _find_first_bit_le(p,sz) @@ -215,16 +206,9 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); #define WORD_BITOFF_TO_LE(x) ((x)) #else - /* * These are the big endian, atomic definitions. */ -#define set_bit(nr,p) ATOMIC_BITOP_BE(set_bit,nr,p) -#define clear_bit(nr,p) ATOMIC_BITOP_BE(clear_bit,nr,p) -#define change_bit(nr,p) ATOMIC_BITOP_BE(change_bit,nr,p) -#define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p) -#define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p) -#define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off) #define find_first_bit(p,sz) _find_first_bit_be(p,sz) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 3acd8fa..d5d8d5c 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_V6) -//# 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 - -/* * 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 *); @@ -316,7 +187,8 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *, * Optimized __flush_icache_all for the common cases. Note that UP ARMv7 * will fall through to use __flush_icache_all_generic. */ -#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) || \ +#if (defined(CONFIG_CPU_V7) && \ + (defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K))) || \ defined(CONFIG_SMP_ON_UP) #define __flush_icache_preferred __cpuc_flush_icache_all #elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP) diff --git a/arch/arm/include/asm/cpu-multi32.h b/arch/arm/include/asm/cpu-multi32.h deleted file mode 100644 index e2b5b0b..0000000 --- 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 f073a6d..0000000 --- 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 20ae96c..ed5bc9e 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 0000000..de53547 --- /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 0000000..c7afbc5 --- /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 0000000..354d571 --- /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 0000000..d385f37 --- /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 0000000..e2be7f1 --- /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 234a3fc..0ec35d1 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/gic.h b/arch/arm/include/asm/hardware/gic.h index 84557d3..0691f9d 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/highmem.h b/arch/arm/include/asm/highmem.h index 7080e2c..a4edd19 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/mach/irq.h b/arch/arm/include/asm/mach/irq.h index 22ac140..febe495 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 d0ee74b..431077c 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -15,6 +15,7 @@ #include <linux/compiler.h> #include <linux/const.h> +#include <linux/types.h> #include <mach/memory.h> #include <asm/sizes.h> @@ -133,20 +134,10 @@ #endif /* - * Physical vs virtual RAM address space conversion. These are - * private definitions which should NOT be used outside memory.h - * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. - */ -#ifndef __virt_to_phys -#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) -#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) -#endif - -/* * Convert a physical address to a Page Frame Number and back */ -#define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT) -#define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) +#define __phys_to_pfn(paddr) ((unsigned long)((paddr) >> PAGE_SHIFT)) +#define __pfn_to_phys(pfn) ((phys_addr_t)(pfn) << PAGE_SHIFT) /* * Convert a page to/from a physical address @@ -157,6 +148,62 @@ #ifndef __ASSEMBLY__ /* + * Physical vs virtual RAM address space conversion. These are + * private definitions which should NOT be used outside memory.h + * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. + */ +#ifndef __virt_to_phys +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + +/* + * Constants used to force the right instruction encodings and shifts + * so that all we need to do is modify the 8-bit constant field. + */ +#define __PV_BITS_31_24 0x81000000 +#define __PV_BITS_23_16 0x00810000 + +extern unsigned long __pv_phys_offset; +#define PHYS_OFFSET __pv_phys_offset + +#define __pv_stub(from,to,instr,type) \ + __asm__("@ __pv_stub\n" \ + "1: " instr " %0, %1, %2\n" \ + " .pushsection .pv_table,\"a\"\n" \ + " .long 1b\n" \ + " .popsection\n" \ + : "=r" (to) \ + : "r" (from), "I" (type)) + +static inline unsigned long __virt_to_phys(unsigned long x) +{ + unsigned long t; + __pv_stub(x, t, "add", __PV_BITS_31_24); +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + __pv_stub(t, t, "add", __PV_BITS_23_16); +#endif + return t; +} + +static inline unsigned long __phys_to_virt(unsigned long x) +{ + unsigned long t; + __pv_stub(x, t, "sub", __PV_BITS_31_24); +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + __pv_stub(t, t, "sub", __PV_BITS_23_16); +#endif + return t; +} +#else +#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) +#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) +#endif +#endif + +#ifndef PHYS_OFFSET +#define PHYS_OFFSET PLAT_PHYS_OFFSET +#endif + +/* * The DMA mask corresponding to the maximum bus address allocatable * using GFP_DMA. The default here places no restriction on DMA * allocations. This must be the smallest DMA mask in the system, @@ -188,12 +235,12 @@ * translation for translating DMA addresses. Use the driver * DMA support - see dma-mapping.h. */ -static inline unsigned long virt_to_phys(const volatile void *x) +static inline phys_addr_t virt_to_phys(const volatile void *x) { return __virt_to_phys((unsigned long)(x)); } -static inline void *phys_to_virt(unsigned long x) +static inline void *phys_to_virt(phys_addr_t x) { return (void *)(__phys_to_virt((unsigned long)(x))); } diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 12c8e68..543b449 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h @@ -25,8 +25,31 @@ struct mod_arch_specific { }; /* - * Include the ARM architecture version. + * Add the ARM architecture version to the version magic string */ -#define MODULE_ARCH_VERMAGIC "ARMv" __stringify(__LINUX_ARM_ARCH__) " " +#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " " + +/* Add __virt_to_phys patching state as well */ +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT +#define MODULE_ARCH_VERMAGIC_P2V "p2v16 " +#else +#define MODULE_ARCH_VERMAGIC_P2V "p2v8 " +#endif +#else +#define MODULE_ARCH_VERMAGIC_P2V "" +#endif + +/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */ +#ifdef CONFIG_THUMB2_KERNEL +#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 " +#else +#define MODULE_ARCH_VERMAGIC_ARMTHUMB "" +#endif + +#define MODULE_ARCH_VERMAGIC \ + MODULE_ARCH_VERMAGIC_ARMVSN \ + MODULE_ARCH_VERMAGIC_ARMTHUMB \ + MODULE_ARCH_VERMAGIC_P2V #endif /* _ASM_ARM_MODULE_H */ diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h index fc19009..348d513 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/proc-fns.h b/arch/arm/include/asm/proc-fns.h index 8fdae9b..8ec535e 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 - -#ifdef CONFIG_CPU_V6 -# 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 67357ba..b2d9df5 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 783d50f..a8ff22b 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 2376835..4eb6d00 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/spinlock.h b/arch/arm/include/asm/spinlock.h index 17eb355..fdd3820 100644 --- a/arch/arm/include/asm/spinlock.h +++ b/arch/arm/include/asm/spinlock.h @@ -5,17 +5,52 @@ #error SMP not supported on pre-ARMv6 CPUs #endif +/* + * sev and wfe are ARMv6K extensions. Uniprocessor ARMv6 may not have the K + * extensions, so when running on UP, we have to patch these instructions away. + */ +#define ALT_SMP(smp, up) \ + "9998: " smp "\n" \ + " .pushsection \".alt.smp.init\", \"a\"\n" \ + " .long 9998b\n" \ + " " up "\n" \ + " .popsection\n" + +#ifdef CONFIG_THUMB2_KERNEL +#define SEV ALT_SMP("sev.w", "nop.w") +/* + * For Thumb-2, special care is needed to ensure that the conditional WFE + * instruction really does assemble to exactly 4 bytes (as required by + * the SMP_ON_UP fixup code). By itself "wfene" might cause the + * assembler to insert a extra (16-bit) IT instruction, depending on the + * presence or absence of neighbouring conditional instructions. + * + * To avoid this unpredictableness, an approprite IT is inserted explicitly: + * the assembler won't change IT instructions which are explicitly present + * in the input. + */ +#define WFE(cond) ALT_SMP( \ + "it " cond "\n\t" \ + "wfe" cond ".n", \ + \ + "nop.w" \ +) +#else +#define SEV ALT_SMP("sev", "nop") +#define WFE(cond) ALT_SMP("wfe" cond, "nop") +#endif + static inline void dsb_sev(void) { #if __LINUX_ARM_ARCH__ >= 7 __asm__ __volatile__ ( "dsb\n" - "sev" + SEV ); -#elif defined(CONFIG_CPU_32v6K) +#else __asm__ __volatile__ ( "mcr p15, 0, %0, c7, c10, 4\n" - "sev" + SEV : : "r" (0) ); #endif @@ -46,9 +81,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) __asm__ __volatile__( "1: ldrex %0, [%1]\n" " teq %0, #0\n" -#ifdef CONFIG_CPU_32v6K -" wfene\n" -#endif + WFE("ne") " strexeq %0, %2, [%1]\n" " teqeq %0, #0\n" " bne 1b" @@ -107,9 +140,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw) __asm__ __volatile__( "1: ldrex %0, [%1]\n" " teq %0, #0\n" -#ifdef CONFIG_CPU_32v6K -" wfene\n" -#endif + WFE("ne") " strexeq %0, %2, [%1]\n" " teq %0, #0\n" " bne 1b" @@ -176,9 +207,7 @@ static inline void arch_read_lock(arch_rwlock_t *rw) "1: ldrex %0, [%2]\n" " adds %0, %0, #1\n" " strexpl %1, %0, [%2]\n" -#ifdef CONFIG_CPU_32v6K -" wfemi\n" -#endif + WFE("mi") " rsbpls %0, %1, #0\n" " bmi 1b" : "=&r" (tmp), "=&r" (tmp2) diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 97f6d60..9a87823 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -347,6 +347,7 @@ void cpu_idle_wait(void); #include <asm-generic/cmpxchg-local.h> #if __LINUX_ARM_ARCH__ < 6 +/* min ARCH < ARMv6 */ #ifdef CONFIG_SMP #error "SMP is not supported on this platform" @@ -365,7 +366,7 @@ void cpu_idle_wait(void); #include <asm-generic/cmpxchg.h> #endif -#else /* __LINUX_ARM_ARCH__ >= 6 */ +#else /* min ARCH >= ARMv6 */ extern void __bad_cmpxchg(volatile void *ptr, int size); @@ -379,7 +380,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, unsigned long oldval, res; switch (size) { -#ifdef CONFIG_CPU_32v6K +#ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */ case 1: do { asm volatile("@ __cmpxchg1\n" @@ -404,7 +405,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, : "memory", "cc"); } while (res); break; -#endif /* CONFIG_CPU_32v6K */ +#endif case 4: do { asm volatile("@ __cmpxchg4\n" @@ -450,12 +451,12 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, unsigned long ret; switch (size) { -#ifndef CONFIG_CPU_32v6K +#ifdef CONFIG_CPU_V6 /* min ARCH == ARMv6 */ case 1: case 2: ret = __cmpxchg_local_generic(ptr, old, new, size); break; -#endif /* !CONFIG_CPU_32v6K */ +#endif default: ret = __cmpxchg(ptr, old, new, size); } @@ -469,7 +470,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, (unsigned long)(n), \ sizeof(*(ptr)))) -#ifdef CONFIG_CPU_32v6K +#ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */ /* * Note : ARMv7-M (currently unsupported by Linux) does not support @@ -524,11 +525,11 @@ static inline unsigned long long __cmpxchg64_mb(volatile void *ptr, (unsigned long long)(o), \ (unsigned long long)(n))) -#else /* !CONFIG_CPU_32v6K */ +#else /* min ARCH = ARMv6 */ #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) -#endif /* CONFIG_CPU_32v6K */ +#endif #endif /* __LINUX_ARM_ARCH__ >= 6 */ diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h index e71d6ff..60843eb 100644 --- a/arch/arm/include/asm/tls.h +++ b/arch/arm/include/asm/tls.h @@ -28,15 +28,14 @@ #define tls_emu 1 #define has_tls_reg 1 #define set_tls set_tls_none -#elif __LINUX_ARM_ARCH__ >= 7 || \ - (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K)) -#define tls_emu 0 -#define has_tls_reg 1 -#define set_tls set_tls_v6k -#elif __LINUX_ARM_ARCH__ == 6 +#elif defined(CONFIG_CPU_V6) #define tls_emu 0 #define has_tls_reg (elf_hwcap & HWCAP_TLS) #define set_tls set_tls_v6 +#elif defined(CONFIG_CPU_32v6K) +#define tls_emu 0 +#define has_tls_reg 1 +#define set_tls set_tls_v6k #else #define tls_emu 0 #define has_tls_reg 0 diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index 1b960d5..f90756dc 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 05ac4b0..35917b3 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 185ee82..74554f1 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/armksyms.c b/arch/arm/kernel/armksyms.c index e5e1e53..acca35a 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -140,24 +140,18 @@ EXPORT_SYMBOL(__aeabi_ulcmp); #endif /* bitops */ -EXPORT_SYMBOL(_set_bit_le); -EXPORT_SYMBOL(_test_and_set_bit_le); -EXPORT_SYMBOL(_clear_bit_le); -EXPORT_SYMBOL(_test_and_clear_bit_le); -EXPORT_SYMBOL(_change_bit_le); -EXPORT_SYMBOL(_test_and_change_bit_le); +EXPORT_SYMBOL(_set_bit); +EXPORT_SYMBOL(_test_and_set_bit); +EXPORT_SYMBOL(_clear_bit); +EXPORT_SYMBOL(_test_and_clear_bit); +EXPORT_SYMBOL(_change_bit); +EXPORT_SYMBOL(_test_and_change_bit); EXPORT_SYMBOL(_find_first_zero_bit_le); EXPORT_SYMBOL(_find_next_zero_bit_le); EXPORT_SYMBOL(_find_first_bit_le); EXPORT_SYMBOL(_find_next_bit_le); #ifdef __ARMEB__ -EXPORT_SYMBOL(_set_bit_be); -EXPORT_SYMBOL(_test_and_set_bit_be); -EXPORT_SYMBOL(_clear_bit_be); -EXPORT_SYMBOL(_test_and_clear_bit_be); -EXPORT_SYMBOL(_change_bit_be); -EXPORT_SYMBOL(_test_and_change_bit_be); EXPORT_SYMBOL(_find_first_zero_bit_be); EXPORT_SYMBOL(_find_next_zero_bit_be); EXPORT_SYMBOL(_find_first_bit_be); @@ -170,3 +164,7 @@ EXPORT_SYMBOL(mcount); #endif EXPORT_SYMBOL(__gnu_mcount_nc); #endif + +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT +EXPORT_SYMBOL(__pv_phys_offset); +#endif diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 82da661..927522c 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 c6273a3..d86fcd4 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/debug.S b/arch/arm/kernel/debug.S index a0f0752..d2d983b 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S @@ -25,7 +25,7 @@ .macro addruart, rp, rv .endm -#if defined(CONFIG_CPU_V6) +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) .macro senduart, rd, rx mcr p14, 0, \rd, c0, c5, 0 diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 2b46fea..e8d8856 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/entry-header.S b/arch/arm/kernel/entry-header.S index ae94649..051166c 100644 --- a/arch/arm/kernel/entry-header.S +++ b/arch/arm/kernel/entry-header.S @@ -76,13 +76,13 @@ #ifndef CONFIG_THUMB2_KERNEL .macro svc_exit, rpsr msr spsr_cxsf, \rpsr -#if defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr -#elif defined (CONFIG_CPU_V6) +#if defined(CONFIG_CPU_V6) ldr r0, [sp] strex r1, r2, [sp] @ clear the exclusive monitor ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr +#elif defined(CONFIG_CPU_32v6K) + clrex @ clear the exclusive monitor + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr #else ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr #endif @@ -92,10 +92,10 @@ ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr ldr lr, [sp, #\offset + S_PC]! @ get pc msr spsr_cxsf, r1 @ save in spsr_svc -#if defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor -#elif defined (CONFIG_CPU_V6) +#if defined(CONFIG_CPU_V6) strex r1, r2, [sp] @ clear the exclusive monitor +#elif defined(CONFIG_CPU_32v6K) + clrex @ clear the exclusive monitor #endif .if \fast ldmdb sp, {r1 - lr}^ @ get calling r1 - lr diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index 8f57515..c84b57d 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 814ce1a..6b1e0ad 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 f06ff9f..c9173cf 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -26,14 +26,6 @@ #include <mach/debug-macro.S> #endif -#if (PHYS_OFFSET & 0x001fffff) -#error "PHYS_OFFSET must be at an even 2MiB boundary!" -#endif - -#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) -#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) - - /* * swapper_pg_dir is the virtual address of the initial page table. * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must @@ -41,6 +33,7 @@ * the least significant 16 bits to be 0x8000, but we could probably * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. */ +#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) #if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 #error KERNEL_RAM_VADDR must start at 0xXXXX8000 #endif @@ -48,8 +41,8 @@ .globl swapper_pg_dir .equ swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000 - .macro pgtbl, rd - ldr \rd, =(KERNEL_RAM_PADDR - 0x4000) + .macro pgtbl, rd, phys + add \rd, \phys, #TEXT_OFFSET - 0x4000 .endm #ifdef CONFIG_XIP_KERNEL @@ -87,25 +80,33 @@ 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' + +#ifndef CONFIG_XIP_KERNEL + adr r3, 2f + ldmia r3, {r4, r8} + sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET) + add r8, r8, r4 @ PHYS_OFFSET +#else + ldr r8, =PLAT_PHYS_OFFSET +#endif /* * r1 = machine no, r2 = atags, - * r8 = machinfo, r9 = cpuid, r10 = procinfo + * r8 = phys_offset, r9 = cpuid, r10 = procinfo */ bl __vet_atags #ifdef CONFIG_SMP_ON_UP bl __fixup_smp #endif +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + bl __fixup_pv_table +#endif bl __create_page_tables /* * 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. */ @@ -118,22 +119,24 @@ ENTRY(stext) 1: b __enable_mmu ENDPROC(stext) .ltorg +#ifndef CONFIG_XIP_KERNEL +2: .long . + .long PAGE_OFFSET +#endif /* * Setup the initial page tables. We only setup the barest * amount which are required to get the kernel running, which * generally means mapping in the kernel code. * - * r8 = machinfo - * r9 = cpuid - * r10 = procinfo + * r8 = phys_offset, r9 = cpuid, r10 = procinfo * * Returns: * r0, r3, r5-r7 corrupted * r4 = physical page table address */ __create_page_tables: - pgtbl r4 @ page table address + pgtbl r4, r8 @ page table address /* * Clear the 16K level 1 swapper page table @@ -189,10 +192,8 @@ __create_page_tables: /* * Map some ram to cover our .data and .bss areas. */ - orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000) - .if (KERNEL_RAM_PADDR & 0x00f00000) - orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000) - .endif + add r3, r8, #TEXT_OFFSET + orr r3, r3, r7 add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18 str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]! ldr r6, =(_end - 1) @@ -205,14 +206,17 @@ __create_page_tables: #endif /* - * Then map first 1MB of ram in case it contains our boot params. + * Then map boot params address in r2 or + * the first 1MB of ram if boot params address is not specified. */ - add r0, r4, #PAGE_OFFSET >> 18 - orr r6, r7, #(PHYS_OFFSET & 0xff000000) - .if (PHYS_OFFSET & 0x00f00000) - orr r6, r6, #(PHYS_OFFSET & 0x00f00000) - .endif - str r6, [r0] + mov r0, r2, lsr #20 + movs r0, r0, lsl #20 + moveq r0, r8 + sub r3, r0, r8 + add r3, r3, #PAGE_OFFSET + add r3, r4, r3, lsr #18 + orr r6, r7, r0 + str r6, [r3] #ifdef CONFIG_DEBUG_LL #ifndef CONFIG_DEBUG_ICEDCC @@ -457,4 +461,129 @@ ENTRY(fixup_smp) ldmfd sp!, {r4 - r6, pc} ENDPROC(fixup_smp) +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + +/* __fixup_pv_table - patch the stub instructions with the delta between + * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and + * can be expressed by an immediate shifter operand. The stub instruction + * has a form of '(add|sub) rd, rn, #imm'. + */ + __HEAD +__fixup_pv_table: + adr r0, 1f + ldmia r0, {r3-r5, r7} + sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET + add r4, r4, r3 @ adjust table start address + add r5, r5, r3 @ adjust table end address + add r7, r7, r3 @ adjust __pv_phys_offset address + str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset +#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + mov r6, r3, lsr #24 @ constant for add/sub instructions + teq r3, r6, lsl #24 @ must be 16MiB aligned +#else + mov r6, r3, lsr #16 @ constant for add/sub instructions + teq r3, r6, lsl #16 @ must be 64kiB aligned +#endif +THUMB( it ne @ cross section branch ) + bne __error + str r6, [r7, #4] @ save to __pv_offset + b __fixup_a_pv_table +ENDPROC(__fixup_pv_table) + + .align +1: .long . + .long __pv_table_begin + .long __pv_table_end +2: .long __pv_phys_offset + + .text +__fixup_a_pv_table: +#ifdef CONFIG_THUMB2_KERNEL +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + lsls r0, r6, #24 + lsr r6, #8 + beq 1f + clz r7, r0 + lsr r0, #24 + lsl r0, r7 + bic r0, 0x0080 + lsrs r7, #1 + orrcs r0, #0x0080 + orr r0, r0, r7, lsl #12 +#endif +1: lsls r6, #24 + beq 4f + clz r7, r6 + lsr r6, #24 + lsl r6, r7 + bic r6, #0x0080 + lsrs r7, #1 + orrcs r6, #0x0080 + orr r6, r6, r7, lsl #12 + orr r6, #0x4000 + b 4f +2: @ at this point the C flag is always clear + add r7, r3 +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + ldrh ip, [r7] + tst ip, 0x0400 @ the i bit tells us LS or MS byte + beq 3f + cmp r0, #0 @ set C flag, and ... + biceq ip, 0x0400 @ immediate zero value has a special encoding + streqh ip, [r7] @ that requires the i bit cleared +#endif +3: ldrh ip, [r7, #2] + and ip, 0x8f00 + orrcc ip, r6 @ mask in offset bits 31-24 + orrcs ip, r0 @ mask in offset bits 23-16 + strh ip, [r7, #2] +4: cmp r4, r5 + ldrcc r7, [r4], #4 @ use branch for delay slot + bcc 2b + bx lr +#else +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT + and r0, r6, #255 @ offset bits 23-16 + mov r6, r6, lsr #8 @ offset bits 31-24 +#else + mov r0, #0 @ just in case... +#endif + b 3f +2: ldr ip, [r7, r3] + bic ip, ip, #0x000000ff + tst ip, #0x400 @ rotate shift tells us LS or MS byte + orrne ip, ip, r6 @ mask in offset bits 31-24 + orreq ip, ip, r0 @ mask in offset bits 23-16 + str ip, [r7, r3] +3: cmp r4, r5 + ldrcc r7, [r4], #4 @ use branch for delay slot + bcc 2b + mov pc, lr +#endif +ENDPROC(__fixup_a_pv_table) + +ENTRY(fixup_pv_table) + stmfd sp!, {r4 - r7, lr} + ldr r2, 2f @ get address of __pv_phys_offset + mov r3, #0 @ no offset + mov r4, r0 @ r0 = table start + add r5, r0, r1 @ r1 = table size + ldr r6, [r2, #4] @ get __pv_offset + bl __fixup_a_pv_table + ldmfd sp!, {r4 - r7, pc} +ENDPROC(fixup_pv_table) + + .align +2: .long __pv_phys_offset + + .data + .globl __pv_phys_offset + .type __pv_phys_offset, %object +__pv_phys_offset: + .long 0 + .size __pv_phys_offset, . - __pv_phys_offset +__pv_offset: + .long 0 +#endif + #include "head-common.S" diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 28536e3..3535d37 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/module.c b/arch/arm/kernel/module.c index 6d4105e..fee7c36 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -76,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; @@ -83,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; } @@ -120,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; } @@ -196,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; } @@ -282,12 +283,13 @@ static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr, return NULL; } +extern void fixup_pv_table(const void *, unsigned long); 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; + const Elf_Shdr *s = NULL; #ifdef CONFIG_ARM_UNWIND const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; @@ -332,6 +334,11 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, maps[i].txt_sec->sh_addr, maps[i].txt_sec->sh_size); #endif +#ifdef CONFIG_ARM_PATCH_PHYS_VIRT + s = find_mod_section(hdr, sechdrs, ".pv_table"); + if (s) + fixup_pv_table((void *)s->sh_addr, s->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); diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index c058bfc..6fc2d22 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c @@ -30,7 +30,7 @@ * enable the interrupt. */ -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) enum armv6_perf_types { ARMV6_PERFCTR_ICACHE_MISS = 0x0, ARMV6_PERFCTR_IBUF_STALL = 0x1, @@ -669,4 +669,4 @@ static const struct arm_pmu *__init armv6mpcore_pmu_init(void) { return NULL; } -#endif /* CONFIG_CPU_V6 */ +#endif /* CONFIG_CPU_V6 || CONFIG_CPU_V6K */ diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index b13e70f..2bf27f3 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; diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h deleted file mode 100644 index 3926605..0000000 --- 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 df246da..0b13a72 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 5ea4fb7..d1da921 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -308,7 +308,22 @@ 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 void __init feat_v6_fixup(void) { @@ -426,21 +441,29 @@ void cpu_init(void) static struct machine_desc * __init setup_machine(unsigned int nr) { - struct machine_desc *list; + extern struct machine_desc __arch_info_begin[], __arch_info_end[]; + struct machine_desc *p; /* * locate machine in the list of supported machines. */ - list = lookup_machine_type(nr); - if (!list) { - printk("Machine configuration botched (nr %d), unable " - "to continue.\n", nr); - while (1); - } + for (p = __arch_info_begin; p < __arch_info_end; p++) + if (nr == p->nr) { + printk("Machine: %s\n", p->name); + return p; + } - printk("Machine: %s\n", list->name); + early_print("\n" + "Error: unrecognized/unsupported machine ID (r1 = 0x%08x).\n\n" + "Available machine support:\n\nID (hex)\tNAME\n", nr); - return list; + 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 int __init arm_add_memory(unsigned long start, unsigned long size) @@ -703,7 +726,7 @@ static struct init_tags { { tag_size(tag_core), ATAG_CORE }, { 1, PAGE_SIZE, 0xff }, { tag_size(tag_mem32), ATAG_MEM }, - { MEM_SIZE, PHYS_OFFSET }, + { MEM_SIZE }, { 0, ATAG_NONE } }; @@ -802,6 +825,8 @@ void __init setup_arch(char **cmdline_p) struct machine_desc *mdesc; char *from = default_command_line; + init_tags.mem.start = PHYS_OFFSET; + unwind_init(); setup_processor(); @@ -814,8 +839,25 @@ void __init setup_arch(char **cmdline_p) if (__atags_pointer) tags = phys_to_virt(__atags_pointer); - else if (mdesc->boot_params) - tags = phys_to_virt(mdesc->boot_params); + else if (mdesc->boot_params) { +#ifdef CONFIG_MMU + /* + * We still are executing with a minimal MMU mapping created + * with the presumption that the machine default for this + * is located in the first MB of RAM. Anything else will + * fault and silently hang the kernel at this point. + */ + if (mdesc->boot_params < PHYS_OFFSET || + mdesc->boot_params >= PHYS_OFFSET + SZ_1M) { + printk(KERN_WARNING + "Default boot params at physical 0x%08lx out of reach\n", + mdesc->boot_params); + } else +#endif + { + tags = phys_to_virt(mdesc->boot_params); + } + } #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) /* diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index abaf844..cb83983 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: @@ -706,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; @@ -726,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; } @@ -772,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 0000000..bfad698 --- /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 9ab4149..a1e757c 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/tcm.c b/arch/arm/kernel/tcm.c index 26685c2..f5cf660 100644 --- a/arch/arm/kernel/tcm.c +++ b/arch/arm/kernel/tcm.c @@ -15,7 +15,7 @@ #include <linux/string.h> /* memcpy */ #include <asm/cputype.h> #include <asm/mach/map.h> -#include <mach/memory.h> +#include <asm/memory.h> #include "tcm.h" static struct gen_pool *tcm_pool; diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index ee57640..21ac43f 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 28fea9b..b4348e6 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -64,6 +64,10 @@ SECTIONS __smpalt_end = .; #endif + __pv_table_begin = .; + *(.pv_table) + __pv_table_end = .; + INIT_SETUP(16) INIT_CALLS diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h index d422529..10d868a 100644 --- a/arch/arm/lib/bitops.h +++ b/arch/arm/lib/bitops.h @@ -1,44 +1,52 @@ - -#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K) +#if __LINUX_ARM_ARCH__ >= 6 .macro bitop, instr + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned mov r2, #1 - and r3, r0, #7 @ Get bit offset - add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #31 @ Get bit offset + mov r0, r0, lsr #5 + add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 -1: ldrexb r2, [r1] +1: ldrex r2, [r1] \instr r2, r2, r3 - strexb r0, r2, [r1] + strex r0, r2, [r1] cmp r0, #0 bne 1b - mov pc, lr + bx lr .endm .macro testop, instr, store - and r3, r0, #7 @ Get bit offset + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned mov r2, #1 - add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #31 @ Get bit offset + mov r0, r0, lsr #5 + add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 @ create mask smp_dmb -1: ldrexb r2, [r1] +1: ldrex r2, [r1] ands r0, r2, r3 @ save old value of bit - \instr r2, r2, r3 @ toggle bit - strexb ip, r2, [r1] + \instr r2, r2, r3 @ toggle bit + strex ip, r2, [r1] cmp ip, #0 bne 1b smp_dmb cmp r0, #0 movne r0, #1 -2: mov pc, lr +2: bx lr .endm #else .macro bitop, instr - and r2, r0, #7 + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned + and r2, r0, #31 + mov r0, r0, lsr #5 mov r3, #1 mov r3, r3, lsl r2 save_and_disable_irqs ip - ldrb r2, [r1, r0, lsr #3] + ldr r2, [r1, r0, lsl #2] \instr r2, r2, r3 - strb r2, [r1, r0, lsr #3] + str r2, [r1, r0, lsl #2] restore_irqs ip mov pc, lr .endm @@ -52,11 +60,13 @@ * to avoid dirtying the data cache. */ .macro testop, instr, store - add r1, r1, r0, lsr #3 - and r3, r0, #7 - mov r0, #1 + ands ip, r1, #3 + strneb r1, [ip] @ assert word-aligned + and r3, r0, #31 + mov r0, r0, lsr #5 save_and_disable_irqs ip - ldrb r2, [r1] + ldr r2, [r1, r0, lsl #2]! + mov r0, #1 tst r2, r0, lsl r3 \instr r2, r2, r0, lsl r3 \store r2, [r1] diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S index 80f3115..68ed5b6 100644 --- a/arch/arm/lib/changebit.S +++ b/arch/arm/lib/changebit.S @@ -12,12 +12,6 @@ #include "bitops.h" .text -/* Purpose : Function to change a bit - * Prototype: int change_bit(int bit, void *addr) - */ -ENTRY(_change_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_change_bit_le) +ENTRY(_change_bit) bitop eor -ENDPROC(_change_bit_be) -ENDPROC(_change_bit_le) +ENDPROC(_change_bit) diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S index 1a63e43..4c04c3b 100644 --- a/arch/arm/lib/clearbit.S +++ b/arch/arm/lib/clearbit.S @@ -12,13 +12,6 @@ #include "bitops.h" .text -/* - * Purpose : Function to clear a bit - * Prototype: int clear_bit(int bit, void *addr) - */ -ENTRY(_clear_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_clear_bit_le) +ENTRY(_clear_bit) bitop bic -ENDPROC(_clear_bit_be) -ENDPROC(_clear_bit_le) +ENDPROC(_clear_bit) diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S index 1dd7176..bbee5c6 100644 --- a/arch/arm/lib/setbit.S +++ b/arch/arm/lib/setbit.S @@ -12,13 +12,6 @@ #include "bitops.h" .text -/* - * Purpose : Function to set a bit - * Prototype: int set_bit(int bit, void *addr) - */ -ENTRY(_set_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_set_bit_le) +ENTRY(_set_bit) bitop orr -ENDPROC(_set_bit_be) -ENDPROC(_set_bit_le) +ENDPROC(_set_bit) diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S index 5c98dc5..15a4d43 100644 --- a/arch/arm/lib/testchangebit.S +++ b/arch/arm/lib/testchangebit.S @@ -12,9 +12,6 @@ #include "bitops.h" .text -ENTRY(_test_and_change_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_test_and_change_bit_le) - testop eor, strb -ENDPROC(_test_and_change_bit_be) -ENDPROC(_test_and_change_bit_le) +ENTRY(_test_and_change_bit) + testop eor, str +ENDPROC(_test_and_change_bit) diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S index 543d709..521b66b 100644 --- a/arch/arm/lib/testclearbit.S +++ b/arch/arm/lib/testclearbit.S @@ -12,9 +12,6 @@ #include "bitops.h" .text -ENTRY(_test_and_clear_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_test_and_clear_bit_le) - testop bicne, strneb -ENDPROC(_test_and_clear_bit_be) -ENDPROC(_test_and_clear_bit_le) +ENTRY(_test_and_clear_bit) + testop bicne, strne +ENDPROC(_test_and_clear_bit) diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S index 0b3f390..1c98cc2 100644 --- a/arch/arm/lib/testsetbit.S +++ b/arch/arm/lib/testsetbit.S @@ -12,9 +12,6 @@ #include "bitops.h" .text -ENTRY(_test_and_set_bit_be) - eor r0, r0, #0x18 @ big endian byte ordering -ENTRY(_test_and_set_bit_le) - testop orreq, streqb -ENDPROC(_test_and_set_bit_be) -ENDPROC(_test_and_set_bit_le) +ENTRY(_test_and_set_bit) + testop orreq, streq +ENDPROC(_test_and_set_bit) diff --git a/arch/arm/mach-aaec2000/include/mach/memory.h b/arch/arm/mach-aaec2000/include/mach/memory.h index 4f93c56..4a10bf0 100644 --- a/arch/arm/mach-aaec2000/include/mach/memory.h +++ b/arch/arm/mach-aaec2000/include/mach/memory.h @@ -12,6 +12,6 @@ #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0xf0000000) +#define PLAT_PHYS_OFFSET UL(0xf0000000) #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c index 0a99b3c..17f7d9b 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 bfdd8ab..ddeb645 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-at91/include/mach/memory.h b/arch/arm/mach-at91/include/mach/memory.h index 14f4ef4..c2cfe50 100644 --- a/arch/arm/mach-at91/include/mach/memory.h +++ b/arch/arm/mach-at91/include/mach/memory.h @@ -23,6 +23,6 @@ #include <mach/hardware.h> -#define PHYS_OFFSET (AT91_SDRAM_BASE) +#define PLAT_PHYS_OFFSET (AT91_SDRAM_BASE) #endif diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h index 447eb34..8bf3564 100644 --- a/arch/arm/mach-bcmring/include/mach/hardware.h +++ b/arch/arm/mach-bcmring/include/mach/hardware.h @@ -31,7 +31,7 @@ * *_SIZE is the size of the region * *_BASE is the virtual address */ -#define RAM_START PHYS_OFFSET +#define RAM_START PLAT_PHYS_OFFSET #define RAM_SIZE (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED) #define RAM_BASE PAGE_OFFSET diff --git a/arch/arm/mach-bcmring/include/mach/memory.h b/arch/arm/mach-bcmring/include/mach/memory.h index 114f942..15162e4 100644 --- a/arch/arm/mach-bcmring/include/mach/memory.h +++ b/arch/arm/mach-bcmring/include/mach/memory.h @@ -23,7 +23,7 @@ * files. Use virt_to_phys/phys_to_virt/__pa/__va instead. */ -#define PHYS_OFFSET CFG_GLOBAL_RAM_BASE +#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE /* * Maximum DMA memory allowed is 14M diff --git a/arch/arm/mach-clps711x/include/mach/memory.h b/arch/arm/mach-clps711x/include/mach/memory.h index f45c8e8..3a032a6 100644 --- a/arch/arm/mach-clps711x/include/mach/memory.h +++ b/arch/arm/mach-clps711x/include/mach/memory.h @@ -23,7 +23,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) #if !defined(CONFIG_ARCH_CDB89712) && !defined (CONFIG_ARCH_AUTCPU12) diff --git a/arch/arm/mach-cns3xxx/include/mach/memory.h b/arch/arm/mach-cns3xxx/include/mach/memory.h index 3b6b769..dc16c5c 100644 --- a/arch/arm/mach-cns3xxx/include/mach/memory.h +++ b/arch/arm/mach-cns3xxx/include/mach/memory.h @@ -13,7 +13,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define __phys_to_bus(x) ((x) + PHYS_OFFSET) #define __bus_to_phys(x) ((x) - PHYS_OFFSET) diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h index 22eb97c..7882272 100644 --- a/arch/arm/mach-davinci/include/mach/memory.h +++ b/arch/arm/mach-davinci/include/mach/memory.h @@ -26,9 +26,9 @@ #if defined(CONFIG_ARCH_DAVINCI_DA8XX) && defined(CONFIG_ARCH_DAVINCI_DMx) #error Cannot enable DaVinci and DA8XX platforms concurrently #elif defined(CONFIG_ARCH_DAVINCI_DA8XX) -#define PHYS_OFFSET DA8XX_DDR_BASE +#define PLAT_PHYS_OFFSET DA8XX_DDR_BASE #else -#define PHYS_OFFSET DAVINCI_DDR_BASE +#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE #endif #define DDR2_SDRCR_OFFSET 0xc diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig index a4ed390..dd937c5 100644 --- a/arch/arm/mach-dove/Kconfig +++ b/arch/arm/mach-dove/Kconfig @@ -9,7 +9,7 @@ config MACH_DOVE_DB Say 'Y' here if you want your kernel to support the Marvell DB-MV88AP510 Development Board. - config MACH_CM_A510 +config MACH_CM_A510 bool "CompuLab CM-A510 Board" help Say 'Y' here if you want your kernel to support the diff --git a/arch/arm/mach-dove/include/mach/memory.h b/arch/arm/mach-dove/include/mach/memory.h index d668720..bbc93fe 100644 --- a/arch/arm/mach-dove/include/mach/memory.h +++ b/arch/arm/mach-dove/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ebsa110/include/mach/memory.h b/arch/arm/mach-ebsa110/include/mach/memory.h index 0ca66d0..8e49066 100644 --- a/arch/arm/mach-ebsa110/include/mach/memory.h +++ b/arch/arm/mach-ebsa110/include/mach/memory.h @@ -19,7 +19,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) /* * Cache flushing area - SRAM diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index 4b04316..9969bb1 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 bec34b8..a889fa7 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); @@ -434,6 +447,18 @@ void __init ep93xx_gpio_init(void) EP93XX_SYSCON_DEVCFG_GONIDE | EP93XX_SYSCON_DEVCFG_HONIDE); - for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) - gpiochip_add(&ep93xx_gpio_banks[i].chip); + 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 c991b14..c57152c 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-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h index 554064e..c9400cf 100644 --- a/arch/arm/mach-ep93xx/include/mach/memory.h +++ b/arch/arm/mach-ep93xx/include/mach/memory.h @@ -6,15 +6,15 @@ #define __ASM_ARCH_MEMORY_H #if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) #elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xd0000000) +#define PLAT_PHYS_OFFSET UL(0xd0000000) #elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xe0000000) +#define PLAT_PHYS_OFFSET UL(0xe0000000) #elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) -#define PHYS_OFFSET UL(0xf0000000) +#define PLAT_PHYS_OFFSET UL(0xf0000000) #else #error "Kconfig bug: No EP93xx PHYS_OFFSET set" #endif diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c index bc5e83f..a921fe9 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/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h index 51dd902..b6fdf23 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 101a4fe..32e4cc3 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/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h index 8d64f45..5c6df37 100644 --- a/arch/arm/mach-footbridge/include/mach/memory.h +++ b/arch/arm/mach-footbridge/include/mach/memory.h @@ -62,7 +62,7 @@ extern unsigned long __bus_to_pfn(unsigned long); /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define FLUSH_BASE_PHYS 0x50000000 diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c index f488fa2..441c6ce 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 2ba096d..0cf7a07 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 a9a0d8b..4fa09af 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 8b88d50..af7b68a 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 1eebcec..99e5bbe 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 9392834..7670c39 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 6b52525..5cff298 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-gemini/include/mach/memory.h b/arch/arm/mach-gemini/include/mach/memory.h index 2d14d5b..a50915f 100644 --- a/arch/arm/mach-gemini/include/mach/memory.h +++ b/arch/arm/mach-gemini/include/mach/memory.h @@ -11,9 +11,9 @@ #define __MACH_MEMORY_H #ifdef CONFIG_GEMINI_MEM_SWAP -# define PHYS_OFFSET UL(0x00000000) +# define PLAT_PHYS_OFFSET UL(0x00000000) #else -# define PHYS_OFFSET UL(0x10000000) +# define PLAT_PHYS_OFFSET UL(0x10000000) #endif #endif /* __MACH_MEMORY_H */ diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h index ef4c1e2..9d36876 100644 --- a/arch/arm/mach-h720x/include/mach/memory.h +++ b/arch/arm/mach-h720x/include/mach/memory.h @@ -7,7 +7,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x40000000) +#define PLAT_PHYS_OFFSET UL(0x40000000) /* * This is the maximum DMA address that can be DMAd to. * There should not be more than (0xd0000000 - 0xc0000000) diff --git a/arch/arm/mach-integrator/include/mach/memory.h b/arch/arm/mach-integrator/include/mach/memory.h index 991f24d..334d5e2 100644 --- a/arch/arm/mach-integrator/include/mach/memory.h +++ b/arch/arm/mach-integrator/include/mach/memory.h @@ -23,7 +23,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define BUS_OFFSET UL(0x80000000) #define __virt_to_bus(x) ((x) - PAGE_OFFSET + BUS_OFFSET) diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h index 3ad4553..1afa99e 100644 --- a/arch/arm/mach-iop13xx/include/mach/memory.h +++ b/arch/arm/mach-iop13xx/include/mach/memory.h @@ -6,7 +6,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-iop32x/include/mach/memory.h b/arch/arm/mach-iop32x/include/mach/memory.h index c30f645..169cc23 100644 --- a/arch/arm/mach-iop32x/include/mach/memory.h +++ b/arch/arm/mach-iop32x/include/mach/memory.h @@ -8,6 +8,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xa0000000) +#define PLAT_PHYS_OFFSET UL(0xa0000000) #endif diff --git a/arch/arm/mach-iop33x/include/mach/memory.h b/arch/arm/mach-iop33x/include/mach/memory.h index a30a96a..8e1daf7 100644 --- a/arch/arm/mach-iop33x/include/mach/memory.h +++ b/arch/arm/mach-iop33x/include/mach/memory.h @@ -8,6 +8,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ixp2000/include/mach/memory.h b/arch/arm/mach-ixp2000/include/mach/memory.h index 98e3471..5f0c4fd 100644 --- a/arch/arm/mach-ixp2000/include/mach/memory.h +++ b/arch/arm/mach-ixp2000/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #include <mach/ixp2000-regs.h> diff --git a/arch/arm/mach-ixp23xx/include/mach/memory.h b/arch/arm/mach-ixp23xx/include/mach/memory.h index 6ef65d8..6cf0704 100644 --- a/arch/arm/mach-ixp23xx/include/mach/memory.h +++ b/arch/arm/mach-ixp23xx/include/mach/memory.h @@ -17,7 +17,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET (0x00000000) +#define PLAT_PHYS_OFFSET (0x00000000) #define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0) diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h index 0136eaa..6d388c9 100644 --- a/arch/arm/mach-ixp4xx/include/mach/memory.h +++ b/arch/arm/mach-ixp4xx/include/mach/memory.h @@ -12,7 +12,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #if !defined(__ASSEMBLY__) && defined(CONFIG_PCI) diff --git a/arch/arm/mach-kirkwood/include/mach/memory.h b/arch/arm/mach-kirkwood/include/mach/memory.h index 45431e1..4600b44 100644 --- a/arch/arm/mach-kirkwood/include/mach/memory.h +++ b/arch/arm/mach-kirkwood/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h index bace9a6..f7e1b9b 100644 --- a/arch/arm/mach-ks8695/include/mach/memory.h +++ b/arch/arm/mach-ks8695/include/mach/memory.h @@ -18,7 +18,7 @@ /* * Physical SRAM offset. */ -#define PHYS_OFFSET KS8695_SDRAM_PA +#define PLAT_PHYS_OFFSET KS8695_SDRAM_PA #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-lh7a40x/include/mach/memory.h b/arch/arm/mach-lh7a40x/include/mach/memory.h index edb8f5f..f77bde8 100644 --- a/arch/arm/mach-lh7a40x/include/mach/memory.h +++ b/arch/arm/mach-lh7a40x/include/mach/memory.h @@ -17,7 +17,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) /* * Sparsemem version of the above diff --git a/arch/arm/mach-loki/include/mach/memory.h b/arch/arm/mach-loki/include/mach/memory.h index 2ed7e6e7..6636665 100644 --- a/arch/arm/mach-loki/include/mach/memory.h +++ b/arch/arm/mach-loki/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-lpc32xx/include/mach/memory.h b/arch/arm/mach-lpc32xx/include/mach/memory.h index 044e1ac..a647dd6 100644 --- a/arch/arm/mach-lpc32xx/include/mach/memory.h +++ b/arch/arm/mach-lpc32xx/include/mach/memory.h @@ -22,6 +22,6 @@ /* * Physical DRAM offset of bank 0 */ -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/mach-mmp/include/mach/memory.h b/arch/arm/mach-mmp/include/mach/memory.h index bdb21d7..d68b50a 100644 --- a/arch/arm/mach-mmp/include/mach/memory.h +++ b/arch/arm/mach-mmp/include/mach/memory.h @@ -9,6 +9,6 @@ #ifndef __ASM_MACH_MEMORY_H #define __ASM_MACH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif /* __ASM_MACH_MEMORY_H */ diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c index e7a76ef..08fcd40 100644 --- a/arch/arm/mach-msm/board-msm7x27.c +++ b/arch/arm/mach-msm/board-msm7x27.c @@ -132,7 +132,7 @@ static void __init msm7x2x_map_io(void) MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, @@ -142,7 +142,7 @@ MACHINE_END MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, @@ -152,7 +152,7 @@ MACHINE_END MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, @@ -162,7 +162,7 @@ MACHINE_END MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c index 6f3b973..25db8fd 100644 --- a/arch/arm/mach-msm/board-msm7x30.c +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -26,11 +26,11 @@ #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/memory.h> #include <asm/setup.h> #include <mach/gpio.h> #include <mach/board.h> -#include <mach/memory.h> #include <mach/msm_iomap.h> #include <mach/dma.h> @@ -85,7 +85,7 @@ static void __init msm7x30_map_io(void) MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, @@ -95,7 +95,7 @@ MACHINE_END MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, @@ -105,7 +105,7 @@ MACHINE_END MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x30_map_io, .init_irq = msm7x30_init_irq, .init_machine = msm7x30_init, diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c index 6dde818..15c2bbd 100644 --- a/arch/arm/mach-msm/board-qsd8x50.c +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -118,7 +118,7 @@ static void __init qsd8x50_init(void) MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = qsd8x50_map_io, .init_irq = qsd8x50_init_irq, .init_machine = qsd8x50_init, @@ -128,7 +128,7 @@ MACHINE_END MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5") #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = qsd8x50_map_io, .init_irq = qsd8x50_init_irq, .init_machine = qsd8x50_init, diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c index 8919ffb1..83604f5 100644 --- a/arch/arm/mach-msm/board-sapphire.c +++ b/arch/arm/mach-msm/board-sapphire.c @@ -107,7 +107,7 @@ MACHINE_START(SAPPHIRE, "sapphire") /* Maintainer: Brian Swetland <swetland@google.com> */ #ifdef CONFIG_MSM_DEBUG_UART #endif - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, .fixup = sapphire_fixup, .map_io = sapphire_map_io, .init_irq = sapphire_init_irq, diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index 070e17d..176875d 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -18,15 +18,15 @@ /* physical offset of RAM */ #if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A) -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #elif defined(CONFIG_ARCH_QSD8X50) -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #elif defined(CONFIG_ARCH_MSM7X30) -#define PHYS_OFFSET UL(0x00200000) +#define PLAT_PHYS_OFFSET UL(0x00200000) #elif defined(CONFIG_ARCH_MSM8X60) -#define PHYS_OFFSET UL(0x40200000) +#define PLAT_PHYS_OFFSET UL(0x40200000) #else -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) #endif #endif diff --git a/arch/arm/mach-mv78xx0/include/mach/memory.h b/arch/arm/mach-mv78xx0/include/mach/memory.h index e663042..a648c51 100644 --- a/arch/arm/mach-mv78xx0/include/mach/memory.h +++ b/arch/arm/mach-mv78xx0/include/mach/memory.h @@ -5,6 +5,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-mx3/mach-kzm_arm11_01.c b/arch/arm/mach-mx3/mach-kzm_arm11_01.c index a5f3eb2..df1a6ce 100644 --- a/arch/arm/mach-mx3/mach-kzm_arm11_01.c +++ b/arch/arm/mach-mx3/mach-kzm_arm11_01.c @@ -27,6 +27,7 @@ #include <asm/irq.h> #include <asm/mach-types.h> +#include <asm/memory.h> #include <asm/setup.h> #include <asm/mach/arch.h> #include <asm/mach/irq.h> @@ -36,7 +37,6 @@ #include <mach/clock.h> #include <mach/common.h> #include <mach/iomux-mx3.h> -#include <mach/memory.h> #include "devices-imx31.h" #include "devices.h" diff --git a/arch/arm/mach-mxs/gpio.c b/arch/arm/mach-mxs/gpio.c index cb0c0e8..61991e4 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; @@ -160,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]; @@ -182,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 5dd43ba..0f4c120 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-netx/include/mach/memory.h b/arch/arm/mach-netx/include/mach/memory.h index 9a363f2..5956149 100644 --- a/arch/arm/mach-netx/include/mach/memory.h +++ b/arch/arm/mach-netx/include/mach/memory.h @@ -20,7 +20,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/mach-nomadik/include/mach/memory.h b/arch/arm/mach-nomadik/include/mach/memory.h index 1e5689d..d332521 100644 --- a/arch/arm/mach-nomadik/include/mach/memory.h +++ b/arch/arm/mach-nomadik/include/mach/memory.h @@ -23,6 +23,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-ns9xxx/include/mach/memory.h b/arch/arm/mach-ns9xxx/include/mach/memory.h index 6107193..5c65aee 100644 --- a/arch/arm/mach-ns9xxx/include/mach/memory.h +++ b/arch/arm/mach-ns9xxx/include/mach/memory.h @@ -19,6 +19,6 @@ #define NS9XXX_CS2STAT_LENGTH UL(0x1000) #define NS9XXX_CS3STAT_LENGTH UL(0x1000) -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-nuc93x/include/mach/memory.h b/arch/arm/mach-nuc93x/include/mach/memory.h index 323ab0d..ef9864b 100644 --- a/arch/arm/mach-nuc93x/include/mach/memory.h +++ b/arch/arm/mach-nuc93x/include/mach/memory.h @@ -16,6 +16,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S index 6a0fa04..6285604 100644 --- a/arch/arm/mach-omap1/include/mach/debug-macro.S +++ b/arch/arm/mach-omap1/include/mach/debug-macro.S @@ -17,6 +17,9 @@ #include <plat/serial.h> +#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET) +#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET) + .pushsection .data omap_uart_phys: .word 0x0 omap_uart_virt: .word 0x0 @@ -33,7 +36,7 @@ omap_uart_virt: .word 0x0 /* Use omap_uart_phys/virt if already configured */ 9: mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? - ldreq \rp, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rp, =omap_uart_phys @ MMU enabled add \rv, \rp, #4 @ omap_uart_virt ldr \rp, [\rp, #0] @@ -46,7 +49,7 @@ omap_uart_virt: .word 0x0 mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? ldreq \rp, =OMAP_UART_INFO @ MMU not enabled - ldrne \rp, =__phys_to_virt(OMAP_UART_INFO) @ MMU enabled + ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled ldr \rp, [\rp, #0] /* Select the UART to use based on the UART1 scratchpad value */ @@ -73,7 +76,7 @@ omap_uart_virt: .word 0x0 98: add \rp, \rp, #0xff000000 @ phys base mrc p15, 0, \rv, c1, c0 tst \rv, #1 @ MMU enabled? - ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rv, =omap_uart_phys @ MMU enabled str \rp, [\rv, #0] sub \rp, \rp, #0xff000000 @ phys base diff --git a/arch/arm/mach-omap1/pm.h b/arch/arm/mach-omap1/pm.h index 56a6479..cd926dc 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 ef771ce8..c875bdc 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 7724e52..692587d 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-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 1a2cf62..b69fa0a 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/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S index 6a4d413..6049f46 100644 --- a/arch/arm/mach-omap2/include/mach/debug-macro.S +++ b/arch/arm/mach-omap2/include/mach/debug-macro.S @@ -19,6 +19,9 @@ #define UART_OFFSET(addr) ((addr) & 0x00ffffff) +#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET) +#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET) + .pushsection .data omap_uart_phys: .word 0 omap_uart_virt: .word 0 @@ -36,7 +39,7 @@ omap_uart_lsr: .word 0 /* Use omap_uart_phys/virt if already configured */ 10: mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? - ldreq \rp, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rp, =omap_uart_phys @ MMU enabled add \rv, \rp, #4 @ omap_uart_virt ldr \rp, [\rp, #0] @@ -49,7 +52,7 @@ omap_uart_lsr: .word 0 mrc p15, 0, \rp, c1, c0 tst \rp, #1 @ MMU enabled? ldreq \rp, =OMAP_UART_INFO @ MMU not enabled - ldrne \rp, =__phys_to_virt(OMAP_UART_INFO) @ MMU enabled + ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled ldr \rp, [\rp, #0] /* Select the UART to use based on the UART1 scratchpad value */ @@ -94,7 +97,7 @@ omap_uart_lsr: .word 0 95: ldr \rp, =ZOOM_UART_BASE mrc p15, 0, \rv, c1, c0 tst \rv, #1 @ MMU enabled? - ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rv, =omap_uart_phys @ MMU enabled str \rp, [\rv, #0] ldr \rp, =ZOOM_UART_VIRT @@ -109,7 +112,7 @@ omap_uart_lsr: .word 0 98: add \rp, \rp, #0x48000000 @ phys base mrc p15, 0, \rv, c1, c0 tst \rv, #1 @ MMU enabled? - ldreq \rv, =__virt_to_phys(omap_uart_phys) @ MMU not enabled + ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled ldrne \rv, =omap_uart_phys @ MMU enabled str \rp, [\rv, #0] sub \rp, \rp, #0x48000000 @ phys base @@ -131,7 +134,7 @@ omap_uart_lsr: .word 0 .macro busyuart,rd,rx 1001: mrc p15, 0, \rd, c1, c0 tst \rd, #1 @ MMU enabled? - ldreq \rd, =__virt_to_phys(omap_uart_lsr) @ MMU not enabled + ldreq \rd, =omap_uart_v2p(omap_uart_lsr) @ MMU disabled ldrne \rd, =omap_uart_lsr @ MMU enabled ldr \rd, [\rd, #0] ldrb \rd, [\rx, \rd] diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 1926864..9ef8c29 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.h b/arch/arm/mach-omap2/pm.h index 1c1b0ab..39580e6 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/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index c7780cc..b5071a4 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 98d8232..951a0be 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/sram242x.S b/arch/arm/mach-omap2/sram242x.S index 055310c..ff9b9db 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 f900758..7673020 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 7f893a2..25011ca 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-orion5x/include/mach/memory.h b/arch/arm/mach-orion5x/include/mach/memory.h index 52a2955..6769917 100644 --- a/arch/arm/mach-orion5x/include/mach/memory.h +++ b/arch/arm/mach-orion5x/include/mach/memory.h @@ -7,6 +7,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-pnx4008/include/mach/memory.h b/arch/arm/mach-pnx4008/include/mach/memory.h index 0e87700..1275db6 100644 --- a/arch/arm/mach-pnx4008/include/mach/memory.h +++ b/arch/arm/mach-pnx4008/include/mach/memory.h @@ -16,6 +16,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c index a134a14..e194d92 100644 --- a/arch/arm/mach-pxa/balloon3.c +++ b/arch/arm/mach-pxa/balloon3.c @@ -829,5 +829,5 @@ MACHINE_START(BALLOON3, "Balloon3") .init_irq = balloon3_init_irq, .timer = &pxa_timer, .init_machine = balloon3_init, - .boot_params = PHYS_OFFSET + 0x100, + .boot_params = PLAT_PHYS_OFFSET + 0x100, MACHINE_END diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h index 92361a6..7f68724 100644 --- a/arch/arm/mach-pxa/include/mach/memory.h +++ b/arch/arm/mach-pxa/include/mach/memory.h @@ -15,7 +15,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0xa0000000) +#define PLAT_PHYS_OFFSET UL(0xa0000000) #if !defined(__ASSEMBLY__) && defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI) void cmx2xx_pci_adjust_zones(unsigned long *size, unsigned long *holes); diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h index fd8360c..f15afe0 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/palmz72.c b/arch/arm/mach-pxa/palmz72.c index 7bf4017..3010193 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 1807c9a..51e1583 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -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 b166b1d..6bde595 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; } diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 987301f..28b11be 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 a7a19e1..1230343 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 c551da8..6f53688 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/zeus.c b/arch/arm/mach-pxa/zeus.c index f4b053b..b92aa3b 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-realview/Kconfig b/arch/arm/mach-realview/Kconfig index 7ca138a..b9a9805 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -19,7 +19,7 @@ config REALVIEW_EB_A9MP config REALVIEW_EB_ARM11MP bool "Support ARM11MPCore Tile" depends on MACH_REALVIEW_EB - select CPU_V6 + select CPU_V6K select ARCH_HAS_BARRIERS if SMP help Enable support for the ARM11MPCore tile fitted to the Realview(R) @@ -36,7 +36,7 @@ config REALVIEW_EB_ARM11MP_REVB config MACH_REALVIEW_PB11MP bool "Support RealView(R) Platform Baseboard for ARM11MPCore" - select CPU_V6 + select CPU_V6K select ARM_GIC select HAVE_PATA_PLATFORM select ARCH_HAS_BARRIERS if SMP @@ -45,6 +45,7 @@ config MACH_REALVIEW_PB11MP the ARM11MPCore. This platform has an on-board ARM11MPCore and has support for PCI-E and Compact Flash. +# ARMv6 CPU without K extensions, but does have the new exclusive ops config MACH_REALVIEW_PB1176 bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S" select CPU_V6 diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h index 5dafc15..e05fc2c 100644 --- a/arch/arm/mach-realview/include/mach/memory.h +++ b/arch/arm/mach-realview/include/mach/memory.h @@ -24,9 +24,9 @@ * Physical DRAM offset. */ #ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET -#define PHYS_OFFSET UL(0x70000000) +#define PLAT_PHYS_OFFSET UL(0x70000000) #else -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif #if !defined(__ASSEMBLY__) && defined(CONFIG_ZONE_DMA) diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 6ef5c5e..8ede983 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -484,7 +484,7 @@ static void __init realview_eb_init(void) MACHINE_START(REALVIEW_EB, "ARM-RealView EB") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_eb_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index cbdc97a..9f26369 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -379,7 +379,7 @@ static void __init realview_pb1176_init(void) MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_pb1176_fixup, .map_io = realview_pb1176_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 8e8ab7d..dea06b2 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -381,7 +381,7 @@ static void __init realview_pb11mp_init(void) MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_pb11mp_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 841118e..7d0f173 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -331,7 +331,7 @@ static void __init realview_pba8_init(void) MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_fixup, .map_io = realview_pba8_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 02b755b..b89e28f 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -414,7 +414,7 @@ static void __init realview_pbx_init(void) MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */ - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .fixup = realview_pbx_fixup, .map_io = realview_pbx_map_io, .init_irq = gic_init_irq, diff --git a/arch/arm/mach-rpc/include/mach/memory.h b/arch/arm/mach-rpc/include/mach/memory.h index 78191bf..18a22109 100644 --- a/arch/arm/mach-rpc/include/mach/memory.h +++ b/arch/arm/mach-rpc/include/mach/memory.h @@ -21,7 +21,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) /* * Cache flushing area - ROM diff --git a/arch/arm/mach-s3c2400/include/mach/memory.h b/arch/arm/mach-s3c2400/include/mach/memory.h index cf5901f..3f33670 100644 --- a/arch/arm/mach-s3c2400/include/mach/memory.h +++ b/arch/arm/mach-s3c2400/include/mach/memory.h @@ -15,6 +15,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x0C000000) +#define PLAT_PHYS_OFFSET UL(0x0C000000) #endif diff --git a/arch/arm/mach-s3c2410/include/mach/memory.h b/arch/arm/mach-s3c2410/include/mach/memory.h index 6f1e587..f92b97b 100644 --- a/arch/arm/mach-s3c2410/include/mach/memory.h +++ b/arch/arm/mach-s3c2410/include/mach/memory.h @@ -11,6 +11,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x30000000) +#define PLAT_PHYS_OFFSET UL(0x30000000) #endif diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h index 7d74fd5..7d208a7 100644 --- a/arch/arm/mach-s3c24a0/include/mach/memory.h +++ b/arch/arm/mach-s3c24a0/include/mach/memory.h @@ -11,7 +11,7 @@ #ifndef __ASM_ARCH_24A0_MEMORY_H #define __ASM_ARCH_24A0_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) #define __virt_to_bus(x) __virt_to_phys(x) #define __bus_to_virt(x) __phys_to_virt(x) diff --git a/arch/arm/mach-s3c64xx/include/mach/memory.h b/arch/arm/mach-s3c64xx/include/mach/memory.h index 42cc54e..4760cda 100644 --- a/arch/arm/mach-s3c64xx/include/mach/memory.h +++ b/arch/arm/mach-s3c64xx/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x50000000) +#define PLAT_PHYS_OFFSET UL(0x50000000) #define CONSISTENT_DMA_SIZE SZ_8M diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S index b2ef443..afe5a76 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/memory.h b/arch/arm/mach-s5p6442/include/mach/memory.h index 9ddd877..cfe259d 100644 --- a/arch/arm/mach-s5p6442/include/mach/memory.h +++ b/arch/arm/mach-s5p6442/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE SZ_8M #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5p64x0/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h index 1b036b0..365a6eb 100644 --- a/arch/arm/mach-s5p64x0/include/mach/memory.h +++ b/arch/arm/mach-s5p64x0/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE SZ_8M #endif /* __ASM_ARCH_MEMORY_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/memory.h b/arch/arm/mach-s5pc100/include/mach/memory.h index 4b60d18..bda4e79 100644 --- a/arch/arm/mach-s5pc100/include/mach/memory.h +++ b/arch/arm/mach-s5pc100/include/mach/memory.h @@ -13,6 +13,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #endif diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h index d503e0c..7b5fcf0 100644 --- a/arch/arm/mach-s5pv210/include/mach/memory.h +++ b/arch/arm/mach-s5pv210/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #define CONSISTENT_DMA_SIZE (SZ_8M + SZ_4M + SZ_2M) /* diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S index d4d222b..a3d6494 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/include/mach/memory.h b/arch/arm/mach-s5pv310/include/mach/memory.h index 1dffb48..470b01b 100644 --- a/arch/arm/mach-s5pv310/include/mach/memory.h +++ b/arch/arm/mach-s5pv310/include/mach/memory.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H __FILE__ -#define PHYS_OFFSET UL(0x40000000) +#define PLAT_PHYS_OFFSET UL(0x40000000) /* Maximum of 256MiB in one bank */ #define MAX_PHYSMEM_BITS 32 diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h index 128a1df..a44da6a 100644 --- a/arch/arm/mach-sa1100/include/mach/memory.h +++ b/arch/arm/mach-sa1100/include/mach/memory.h @@ -12,7 +12,7 @@ /* * Physical DRAM offset is 0xc0000000 on the SA1100 */ -#define PHYS_OFFSET UL(0xc0000000) +#define PLAT_PHYS_OFFSET UL(0xc0000000) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index ab9fc44..c4661aa 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 80f31ba..04f2a61 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-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h index d9c4812..9afb170 100644 --- a/arch/arm/mach-shark/include/mach/memory.h +++ b/arch/arm/mach-shark/include/mach/memory.h @@ -15,7 +15,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x08000000) +#define PLAT_PHYS_OFFSET UL(0x08000000) #ifndef __ASSEMBLY__ diff --git a/arch/arm/mach-shmobile/include/mach/memory.h b/arch/arm/mach-shmobile/include/mach/memory.h index 377584e..ad00c3c 100644 --- a/arch/arm/mach-shmobile/include/mach/memory.h +++ b/arch/arm/mach-shmobile/include/mach/memory.h @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_MEMORY_H #define __ASM_MACH_MEMORY_H -#define PHYS_OFFSET UL(CONFIG_MEMORY_START) +#define PLAT_PHYS_OFFSET UL(CONFIG_MEMORY_START) #define MEM_SIZE UL(CONFIG_MEMORY_SIZE) /* DMA memory at 0xf6000000 - 0xffdfffff */ 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 0000000..a8d02be --- /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 0000000..4b4f694 --- /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 0000000..f4dc327 --- /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-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c index 18febf9..98bc7ed 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 947625d..53da422 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 af7e02c..8e30636 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 4a86e6a..4660c0d 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 7f940b8..a1a7f48 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 38d767a..5bd8cd8 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 dcca856..63fd983 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 ccaa765..c723515 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 b27bb8a..1e85347 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 53677e4..940f0d8 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 0xB3000000 -#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 5aa2d54..2697e65 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 bb21db1..42d2253 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 53b41b5..5c0a67b 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 7facf66..2d7f333 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 88b4652..741c1f4 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 62ac685..8213e4b 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 52f553c..d3ba8ca 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 36ff056..88b748b 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 9eaecae..8a0b0ed 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 16205a5..94cf4a6 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 7545116..0b3f96a 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 0390803..68c20a0 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 a835f5b..7fd6215 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 5c484c4..d0e6eea 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 daff8d0..f19cefe 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 f2fe14e..9818129 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-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c index 7991415..fb6426d 100644 --- a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c +++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c @@ -54,7 +54,7 @@ static void __init tcc8k_map_io(void) } MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board") - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .map_io = tcc8k_map_io, .init_irq = tcc8k_init_irq, .init_machine = tcc8k_init, diff --git a/arch/arm/mach-tegra/include/mach/memory.h b/arch/arm/mach-tegra/include/mach/memory.h index 6151bab..537db3aa 100644 --- a/arch/arm/mach-tegra/include/mach/memory.h +++ b/arch/arm/mach-tegra/include/mach/memory.h @@ -22,7 +22,7 @@ #define __MACH_TEGRA_MEMORY_H /* physical offset of RAM */ -#define PHYS_OFFSET UL(0) +#define PLAT_PHYS_OFFSET UL(0) #endif diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h index bf134bc..888e2e3 100644 --- a/arch/arm/mach-u300/include/mach/memory.h +++ b/arch/arm/mach-u300/include/mach/memory.h @@ -15,17 +15,17 @@ #ifdef CONFIG_MACH_U300_DUAL_RAM -#define PHYS_OFFSET UL(0x48000000) +#define PLAT_PHYS_OFFSET UL(0x48000000) #define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100) #else #ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX -#define PHYS_OFFSET (0x28000000 + \ +#define PLAT_PHYS_OFFSET (0x28000000 + \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024) #else -#define PHYS_OFFSET (0x28000000 + \ +#define PLAT_PHYS_OFFSET (0x28000000 + \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE + \ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024) #endif diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c index 07c35a8..48b3b7f 100644 --- a/arch/arm/mach-u300/u300.c +++ b/arch/arm/mach-u300/u300.c @@ -19,9 +19,9 @@ #include <linux/io.h> #include <mach/hardware.h> #include <mach/platform.h> -#include <mach/memory.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/memory.h> static void __init u300_reserve(void) { diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 247caa3..203b986 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-ux500/include/mach/memory.h b/arch/arm/mach-ux500/include/mach/memory.h index 510571a..2ef697a 100644 --- a/arch/arm/mach-ux500/include/mach/memory.h +++ b/arch/arm/mach-ux500/include/mach/memory.h @@ -12,7 +12,7 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #define BUS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-versatile/include/mach/memory.h b/arch/arm/mach-versatile/include/mach/memory.h index 79aeab8..dacc9d8 100644 --- a/arch/arm/mach-versatile/include/mach/memory.h +++ b/arch/arm/mach-versatile/include/mach/memory.h @@ -23,6 +23,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index e628402..e9bccc5 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -243,7 +243,7 @@ static void __init ct_ca9x4_init(void) } MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") - .boot_params = PHYS_OFFSET + 0x00000100, + .boot_params = PLAT_PHYS_OFFSET + 0x00000100, .map_io = ct_ca9x4_map_io, .init_irq = ct_ca9x4_init_irq, #if 0 diff --git a/arch/arm/mach-vexpress/include/mach/memory.h b/arch/arm/mach-vexpress/include/mach/memory.h index be28232..5b7fcd4 100644 --- a/arch/arm/mach-vexpress/include/mach/memory.h +++ b/arch/arm/mach-vexpress/include/mach/memory.h @@ -20,6 +20,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x60000000) +#define PLAT_PHYS_OFFSET UL(0x60000000) #endif diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig new file mode 100644 index 0000000..2c20a34 --- /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 0000000..81aedb7 --- /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 0000000..a8acc4e --- /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 0000000..94a261d --- /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 0000000..19519ae --- /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 0000000..db4594e --- /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 0000000..1fcdc36 --- /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 0000000..188d4e1 --- /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 0000000..2bcc0ec --- /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 0000000..f119162 --- /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 0000000..92684c7 --- /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 0000000..94ff276 --- /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 0000000..db4163f --- /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 0000000..cd7143c --- /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 0000000..9077239 --- /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 0000000..a129fd1 --- /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 0000000..175f914 --- /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 0000000..d6c757e --- /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 0000000..8487e4c --- /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 0000000..bb9e2d2 --- /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 0000000..4642290 --- /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 0000000..ecfee91 --- /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 0000000..29c63ec --- /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 0000000..7f399c3 --- /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 0000000..6128627 --- /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 0000000..df15509 --- /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 0000000..5f4ddde --- /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 0000000..8ad825e --- /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 0000000..d5376c5 --- /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 0000000..e73aadb --- /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/mach-w90x900/include/mach/memory.h b/arch/arm/mach-w90x900/include/mach/memory.h index 971b807..f02905b 100644 --- a/arch/arm/mach-w90x900/include/mach/memory.h +++ b/arch/arm/mach-w90x900/include/mach/memory.h @@ -18,6 +18,6 @@ #ifndef __ASM_ARCH_MEMORY_H #define __ASM_ARCH_MEMORY_H -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index e4509ba..8926638 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -390,7 +390,7 @@ config CPU_PJ4 # ARMv6 config CPU_V6 - bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_DOVE + bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX select CPU_32v6 select CPU_ABRT_EV6 select CPU_PABRT_V6 @@ -402,16 +402,18 @@ config CPU_V6 select CPU_TLB_V6 if MMU # ARMv6k -config CPU_32v6K - bool "Support ARM V6K processor extensions" if !SMP - depends on CPU_V6 || CPU_V7 - default y if SMP - help - Say Y here if your ARMv6 processor supports the 'K' extension. - This enables the kernel to use some instructions not present - on previous processors, and as such a kernel build with this - enabled will not boot on processors with do not support these - instructions. +config CPU_V6K + bool "Support ARM V6K processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX + select CPU_32v6 + select CPU_32v6K + select CPU_ABRT_EV6 + select CPU_PABRT_V6 + select CPU_CACHE_V6 + select CPU_CACHE_VIPT + select CPU_CP15_MMU + select CPU_HAS_ASID if MMU + select CPU_COPY_V6 if MMU + select CPU_TLB_V6 if MMU # ARMv7 config CPU_V7 @@ -433,25 +435,33 @@ config CPU_32v3 bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v4 bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v4T bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v5 bool select TLS_REG_EMUL if SMP || !MMU select NEEDS_SYSCALL_FOR_CMPXCHG if SMP + select CPU_USE_DOMAINS if MMU config CPU_32v6 bool select TLS_REG_EMUL if !CPU_32v6K && !MMU + select CPU_USE_DOMAINS if CPU_V6 && MMU + +config CPU_32v6K + bool config CPU_32v7 bool @@ -607,8 +617,6 @@ config CPU_CP15_MPU config CPU_USE_DOMAINS bool - depends on MMU - default y if !CPU_32v6K help This option enables or disables the use of domain switching via the set_fs() function. @@ -623,7 +631,7 @@ comment "Processor Features" config ARM_THUMB bool "Support Thumb user binaries" - depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V7 || CPU_FEROCEON + depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON default y help Say Y if you want to include kernel support for running user space @@ -644,7 +652,7 @@ config ARM_THUMBEE config SWP_EMULATE bool "Emulate SWP/SWPB instructions" - depends on !CPU_USE_DOMAINS && CPU_V7 && !CPU_V6 + depends on !CPU_USE_DOMAINS && CPU_V7 select HAVE_PROC_CPU if PROC_FS default y if SMP help @@ -681,7 +689,7 @@ config CPU_BIG_ENDIAN config CPU_ENDIAN_BE8 bool depends on CPU_BIG_ENDIAN - default CPU_V6 || CPU_V7 + default CPU_V6 || CPU_V6K || CPU_V7 help Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors. @@ -747,7 +755,7 @@ config CPU_CACHE_ROUND_ROBIN config CPU_BPREDICT_DISABLE bool "Disable branch prediction" - depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526 + depends on CPU_ARM1020 || CPU_V6 || CPU_V6K || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526 help Say Y here to disable branch prediction. If unsure, say N. @@ -767,7 +775,7 @@ config NEEDS_SYSCALL_FOR_CMPXCHG config DMA_CACHE_RWFO bool "Enable read/write for ownership DMA cache maintenance" - depends on CPU_V6 && SMP + depends on CPU_V6K && SMP default y help The Snoop Control Unit on ARM11MPCore does not detect the @@ -823,7 +831,7 @@ config CACHE_L2X0 config CACHE_PL310 bool depends on CACHE_L2X0 - default y if CPU_V7 && !CPU_V6 + default y if CPU_V7 && !(CPU_V6 || CPU_V6K) help This option enables optimisations for the PL310 cache controller. @@ -845,16 +853,21 @@ 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 default 5 config ARM_DMA_MEM_BUFFERABLE - bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7 + bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7 depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \ MACH_REALVIEW_PB11MP) - default y if CPU_V6 || CPU_V7 + default y if CPU_V6 || CPU_V6K || CPU_V7 help Historically, the kernel has used strongly ordered mappings to provide DMA coherent memory. With the advent of ARMv7, mapping diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 00d74a0..bca7e61 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o obj-$(CONFIG_CPU_MOHAWK) += proc-mohawk.o obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o obj-$(CONFIG_CPU_V6) += proc-v6.o +obj-$(CONFIG_CPU_V6K) += proc-v6.o obj-$(CONFIG_CPU_V7) += proc-v7.o AFLAGS_proc-v6.o :=-Wa,-march=armv6 diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S index f332df7..1478aa5 100644 --- a/arch/arm/mm/abort-ev6.S +++ b/arch/arm/mm/abort-ev6.S @@ -20,11 +20,11 @@ */ .align 5 ENTRY(v6_early_abort) -#ifdef CONFIG_CPU_32v6K - clrex -#else +#ifdef CONFIG_CPU_V6 sub r1, sp, #4 @ Get unused stack location strex r0, r1, [r1] @ Clear the exclusive monitor +#elif defined(CONFIG_CPU_32v6K) + clrex #endif mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index f2ce38e..ef59099 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -73,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; @@ -97,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; @@ -125,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); } @@ -335,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/mmap.c b/arch/arm/mm/mmap.c index b0a9830..afe209e 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -31,7 +31,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned long start_addr; -#ifdef CONFIG_CPU_V6 +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) unsigned int cache_type; int do_align = 0, aliasing = 0; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 3c67e92..ff7b43b 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 bcf748d..226e3d8 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 ab7ec26..86d9c2c 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 831c5e5..83d3dd3 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 e3f7e9a..686043e 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 6a7be18..5f79dc4 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 c285395..665266d 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 38b27dc..6f9d12e 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 0c9786d..e4c165c 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 6109f27..219980e 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 bb2f0f4..36154b1 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 c13e01a..89c5e000 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 42eb431..6a4bdb2 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 7b11cdb..26aea3f 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 1a5bbf08..8063345 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 db67e31..7b7ebd4 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 7c9ad62..fc2a4ae 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 b4597ed..d3883ee 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 4458ee6..9d4f2ae 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 5aa8d59..46f09ed 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 2ac4e6f..74483d1 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 59a7e1f..832b6bd 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 8e33562..262fa88 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 /* @@ -282,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 @@ -357,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 ec26355..63d8b20 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 5a37c5e..086038c 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 935993e..036fdbf 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/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h index 8386140..5d51cbb 100644 --- a/arch/arm/plat-mxc/include/mach/memory.h +++ b/arch/arm/plat-mxc/include/mach/memory.h @@ -23,23 +23,23 @@ #if !defined(CONFIG_RUNTIME_PHYS_OFFSET) # if defined CONFIG_ARCH_MX1 -# define PHYS_OFFSET MX1_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX1_PHYS_OFFSET # elif defined CONFIG_MACH_MX21 -# define PHYS_OFFSET MX21_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX21_PHYS_OFFSET # elif defined CONFIG_ARCH_MX25 -# define PHYS_OFFSET MX25_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX25_PHYS_OFFSET # elif defined CONFIG_MACH_MX27 -# define PHYS_OFFSET MX27_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX27_PHYS_OFFSET # elif defined CONFIG_ARCH_MX3 -# define PHYS_OFFSET MX3x_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX3x_PHYS_OFFSET # elif defined CONFIG_ARCH_MXC91231 -# define PHYS_OFFSET MXC91231_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MXC91231_PHYS_OFFSET # elif defined CONFIG_ARCH_MX50 -# define PHYS_OFFSET MX50_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX50_PHYS_OFFSET # elif defined CONFIG_ARCH_MX51 -# define PHYS_OFFSET MX51_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX51_PHYS_OFFSET # elif defined CONFIG_ARCH_MX53 -# define PHYS_OFFSET MX53_PHYS_OFFSET +# define PLAT_PHYS_OFFSET MX53_PHYS_OFFSET # endif #endif diff --git a/arch/arm/plat-omap/include/plat/memory.h b/arch/arm/plat-omap/include/plat/memory.h index f8d922f..e6720aa 100644 --- a/arch/arm/plat-omap/include/plat/memory.h +++ b/arch/arm/plat-omap/include/plat/memory.h @@ -37,9 +37,9 @@ * Physical DRAM offset. */ #if defined(CONFIG_ARCH_OMAP1) -#define PHYS_OFFSET UL(0x10000000) +#define PLAT_PHYS_OFFSET UL(0x10000000) #else -#define PHYS_OFFSET UL(0x80000000) +#define PLAT_PHYS_OFFSET UL(0x80000000) #endif /* diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index cec5d56..8ff605c 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -27,7 +27,7 @@ * 2. We assume printascii is called at least once before paging_init, * and addruart has a chance to read OMAP_UART_INFO */ -#define OMAP_UART_INFO (PHYS_OFFSET + 0x3ffc) +#define OMAP_UART_INFO (PLAT_PHYS_OFFSET + 0x3ffc) /* OMAP1 serial ports */ #define OMAP1_UART1_BASE 0xfffb0000 diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h index 9967d5e..f500fc3 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/sram.c b/arch/arm/plat-omap/sram.c index e26e504..68fcc7d 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-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S index e73e3b6e..fd7032f 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-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index 30518cc..937cc2a 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h @@ -52,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 */ /** @@ -181,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 02d531f..d5b58d3 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 eb89540..b4f340b 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 ee4f90e..bdbd7ec 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 2572260..2ae6606 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 e91270e..8501bbf 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 0000000..66d6772 --- /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/memory.h b/arch/arm/plat-spear/include/plat/memory.h index 27a4aba..7e3599e 100644 --- a/arch/arm/plat-spear/include/plat/memory.h +++ b/arch/arm/plat-spear/include/plat/memory.h @@ -15,6 +15,6 @@ #define __PLAT_MEMORY_H /* Physical DRAM offset */ -#define PHYS_OFFSET UL(0x00000000) +#define PLAT_PHYS_OFFSET UL(0x00000000) #endif /* __PLAT_MEMORY_H */ diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-spear/include/plat/system.h index 55a4e40..a235fa0 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 6dd455b..1bf8452 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 diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c index 839c88d..dbb6e4f 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/plat-stmp3xxx/include/mach/memory.h b/arch/arm/plat-stmp3xxx/include/mach/memory.h index 7b875a0..61fa548 100644 --- a/arch/arm/plat-stmp3xxx/include/mach/memory.h +++ b/arch/arm/plat-stmp3xxx/include/mach/memory.h @@ -17,6 +17,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x40000000) +#define PLAT_PHYS_OFFSET UL(0x40000000) #endif diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h index cd91ba8..28a6e0c 100644 --- a/arch/arm/plat-tcc/include/mach/memory.h +++ b/arch/arm/plat-tcc/include/mach/memory.h @@ -13,6 +13,6 @@ /* * Physical DRAM offset. */ -#define PHYS_OFFSET UL(0x20000000) +#define PLAT_PHYS_OFFSET UL(0x20000000) #endif diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 0797cb5..bbf3da0 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. |