From c5ca95b507c8a2a69e49eeda539b41bd76922d7f Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Wed, 18 Dec 2013 23:08:52 +0100 Subject: ARM: 7930/1: Introduce atomic MMIO modify Some SoC have MMIO regions that are shared across orthogonal subsystems. This commit implements a possible solution for the thread-safe access of such regions through a spinlock-protected API. Concurrent access is protected with a single spinlock for the entire MMIO address space. While this protects shared-registers, it also serializes access to unrelated/unshared registers. We add relaxed and non-relaxed variants, by using writel_relaxed and writel, respectively. The rationale for this is that some users may not require register write completion but only thread-safe access to a register. Tested-by: Sebastian Hesselbarth Acked-by: Jason Cooper Acked-by: Catalin Marinas Signed-off-by: Ezequiel Garcia Signed-off-by: Russell King --- arch/arm/include/asm/io.h | 6 ++++++ arch/arm/kernel/io.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index fbeb39c869e9..8aa4cca74501 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -37,6 +37,12 @@ #define isa_page_to_bus page_to_phys #define isa_bus_to_virt phys_to_virt +/* + * Atomic MMIO-wide IO modify + */ +extern void atomic_io_modify(void __iomem *reg, u32 mask, u32 set); +extern void atomic_io_modify_relaxed(void __iomem *reg, u32 mask, u32 set); + /* * Generic IO read/write. These perform native-endian accesses. Note * that some architectures will want to re-define __raw_{read,write}w. diff --git a/arch/arm/kernel/io.c b/arch/arm/kernel/io.c index dcd5b4d86143..9203cf883330 100644 --- a/arch/arm/kernel/io.c +++ b/arch/arm/kernel/io.c @@ -1,6 +1,41 @@ #include #include #include +#include + +static DEFINE_RAW_SPINLOCK(__io_lock); + +/* + * Generic atomic MMIO modify. + * + * Allows thread-safe access to registers shared by unrelated subsystems. + * The access is protected by a single MMIO-wide lock. + */ +void atomic_io_modify_relaxed(void __iomem *reg, u32 mask, u32 set) +{ + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&__io_lock, flags); + value = readl_relaxed(reg) & ~mask; + value |= (set & mask); + writel_relaxed(value, reg); + raw_spin_unlock_irqrestore(&__io_lock, flags); +} +EXPORT_SYMBOL(atomic_io_modify_relaxed); + +void atomic_io_modify(void __iomem *reg, u32 mask, u32 set) +{ + unsigned long flags; + u32 value; + + raw_spin_lock_irqsave(&__io_lock, flags); + value = readl_relaxed(reg) & ~mask; + value |= (set & mask); + writel(value, reg); + raw_spin_unlock_irqrestore(&__io_lock, flags); +} +EXPORT_SYMBOL(atomic_io_modify); /* * Copy data from IO memory space to "real" memory space. -- cgit v1.2.3 From f8fe23ec4e89b58e63085ea92348aff3bcca3e14 Mon Sep 17 00:00:00 2001 From: Victor Kamensky Date: Tue, 21 Jan 2014 06:45:11 +0100 Subject: ARM: 7946/1: asm: __und_usr_thumb need byteswap instructions in BE case __und_usr_thumb function deals with thumb2 opcodes. In case of BE image, it needs to byteswap half word thumb2 encoded instructions before further processing them. Without this fix BE image user-land thread executing first VFP instruction encoded in thumb2 fails with SIGILL, because kernel does not recognize instruction and does not enable VFP. Reported-by: Corey Melton Signed-off-by: Victor Kamensky Tested-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index b3fb8c9e1ff2..1879e8dd2acc 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -451,9 +451,11 @@ __und_usr_thumb: .arch armv6t2 #endif 2: ldrht r5, [r4] +ARM_BE8(rev16 r5, r5) @ little endian instruction cmp r5, #0xe800 @ 32bit instruction if xx != 0 blo __und_usr_fault_16 @ 16bit undefined instruction 3: ldrht r0, [r2] +ARM_BE8(rev16 r0, r0) @ little endian instruction add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 str r2, [sp, #S_PC] @ it's a 2x16bit instr, update orr r0, r0, r5, lsl #16 -- cgit v1.2.3 From 2ab4e8c06dc084c1bba8c8edfa1b33424c16d336 Mon Sep 17 00:00:00 2001 From: Christopher Covington Date: Tue, 21 Jan 2014 16:25:34 +0100 Subject: ARM: 7947/1: Make pgtbl macro more robust The pgtbl macro couldn't handle the specific (TEXT_OFFSET - PG_DIR_SIZE) value that the combination of MSM platforms and LPAE created: head.S:163: Error: invalid constant (203000) after fixup Regardless of whether this combination of configuration options will work on currently support platforms at run time, make it at least assemble properly. Signed-off-by: Christopher Covington Reviewed-by: Stephen Boyd Signed-off-by: Russell King --- arch/arm/kernel/head.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 32f317e5828a..914616e0bdcd 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -52,7 +52,8 @@ .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE .macro pgtbl, rd, phys - add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE + add \rd, \phys, #TEXT_OFFSET + sub \rd, \rd, #PG_DIR_SIZE .endm /* -- cgit v1.2.3 From 4c235cb9e35407bdb4a2debeef4dc8721e8f91f2 Mon Sep 17 00:00:00 2001 From: Ben Peddell Date: Mon, 13 Jan 2014 23:25:18 +0100 Subject: ARM: 7941/2: Fix incorrect FDT initrd parameter override Commit 65939301acdb (arm: set initrd_start/initrd_end for fdt scan) caused the FDT initrd_start and initrd_end to override the phys_initrd_start and phys_initrd_size set by the initrd= kernel parameter. With this patch initrd_start and initrd_end will be overridden if phys_initrd_start and phys_initrd_size are set by the kernel initrd= parameter. Fixes: 65939301acdb (arm: set initrd_start/initrd_end for fdt scan) Signed-off-by: Ben Peddell Acked-by: Jason Cooper Signed-off-by: Russell King --- arch/arm/mm/init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 3e8f106ee5fe..ac1d883460c7 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -345,10 +345,11 @@ void __init arm_memblock_init(struct meminfo *mi, #endif #ifdef CONFIG_BLK_DEV_INITRD /* FDT scan will populate initrd_start */ - if (initrd_start) { + if (initrd_start && !phys_initrd_size) { phys_initrd_start = __virt_to_phys(initrd_start); phys_initrd_size = initrd_end - initrd_start; } + initrd_start = initrd_end = 0; if (phys_initrd_size && !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) { pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n", -- cgit v1.2.3 From d326b65c57d64208646206d0bfd4e2d19d6df38c Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 28 Jan 2014 18:31:17 +0000 Subject: ARM: fix building with gcc 4.6.4 GCC fails to build the kernel if EABI is selected, and the default FPU is selected. Avoid this by explicitly stating that we want VFP with EABI. Signed-off-by: Russell King --- arch/arm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c99b1086d83d..04aa55802ae7 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -100,7 +100,7 @@ tune-$(CONFIG_CPU_V6K) =$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) tune-y := $(tune-y) ifeq ($(CONFIG_AEABI),y) -CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork +CFLAGS_ABI :=-mabi=aapcs-linux -mno-thumb-interwork -mfpu=vfp else CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) endif -- cgit v1.2.3