aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2010-07-01 08:41:05 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-07-09 09:41:34 -0400
commit5aaf254409f8d58229107b59507a8235b715a960 (patch)
tree30b3a289808a34a1db28a0eb6d92bc160be3bc0c /arch
parente513f8bf240d34bd6e732ba2f74df9ab84686ce6 (diff)
ARM: 6203/1: Make VFPv3 usable on ARMv6
MVFR0 and MVFR1 are only available starting with ARM1136 r1p0 release according to "B.5 VFP changes" in DDI0211F_arm1136_r1p0_trm.pdf. This is also when TLS register got added, so we can use HAS_TLS also to test for MVFR0 and MVFR1. Otherwise VFPFMRX and VFPFMXR access fails and we get: Internal error: Oops - undefined instruction: 0 [#1] PC is at no_old_VFP_process+0x8/0x3c LR is at __und_svc+0x48/0x80 ... Signed-off-by: Tony Lindgren <tony@atomide.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/vfpmacros.h18
-rw-r--r--arch/arm/vfp/vfpmodule.c10
2 files changed, 25 insertions, 3 deletions
diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h
index 422f3cc204a2..3d5fc41ae8d3 100644
--- a/arch/arm/include/asm/vfpmacros.h
+++ b/arch/arm/include/asm/vfpmacros.h
@@ -3,6 +3,8 @@
3 * 3 *
4 * Assembler-only file containing VFP macros and register definitions. 4 * Assembler-only file containing VFP macros and register definitions.
5 */ 5 */
6#include <asm/hwcap.h>
7
6#include "vfp.h" 8#include "vfp.h"
7 9
8@ Macros to allow building with old toolkits (with no VFP support) 10@ Macros to allow building with old toolkits (with no VFP support)
@@ -22,12 +24,20 @@
22 LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15} 24 LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15}
23#endif 25#endif
24#ifdef CONFIG_VFPv3 26#ifdef CONFIG_VFPv3
27#if __LINUX_ARM_ARCH__ <= 6
28 ldr \tmp, =elf_hwcap @ may not have MVFR regs
29 ldr \tmp, [\tmp, #0]
30 tst \tmp, #HWCAP_VFPv3D16
31 ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
32 addne \base, \base, #32*4 @ step over unused register space
33#else
25 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 34 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
26 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field 35 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
27 cmp \tmp, #2 @ 32 x 64bit registers? 36 cmp \tmp, #2 @ 32 x 64bit registers?
28 ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} 37 ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
29 addne \base, \base, #32*4 @ step over unused register space 38 addne \base, \base, #32*4 @ step over unused register space
30#endif 39#endif
40#endif
31 .endm 41 .endm
32 42
33 @ write all the working registers out of the VFP 43 @ write all the working registers out of the VFP
@@ -38,10 +48,18 @@
38 STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15} 48 STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15}
39#endif 49#endif
40#ifdef CONFIG_VFPv3 50#ifdef CONFIG_VFPv3
51#if __LINUX_ARM_ARCH__ <= 6
52 ldr \tmp, =elf_hwcap @ may not have MVFR regs
53 ldr \tmp, [\tmp, #0]
54 tst \tmp, #HWCAP_VFPv3D16
55 stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
56 addne \base, \base, #32*4 @ step over unused register space
57#else
41 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 58 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
42 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field 59 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
43 cmp \tmp, #2 @ 32 x 64bit registers? 60 cmp \tmp, #2 @ 32 x 64bit registers?
44 stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} 61 stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
45 addne \base, \base, #32*4 @ step over unused register space 62 addne \base, \base, #32*4 @ step over unused register space
46#endif 63#endif
64#endif
47 .endm 65 .endm
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 315a540c7ce5..8063a322c790 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -15,6 +15,7 @@
15#include <linux/sched.h> 15#include <linux/sched.h>
16#include <linux/init.h> 16#include <linux/init.h>
17 17
18#include <asm/cputype.h>
18#include <asm/thread_notify.h> 19#include <asm/thread_notify.h>
19#include <asm/vfp.h> 20#include <asm/vfp.h>
20 21
@@ -549,10 +550,13 @@ static int __init vfp_init(void)
549 /* 550 /*
550 * Check for the presence of the Advanced SIMD 551 * Check for the presence of the Advanced SIMD
551 * load/store instructions, integer and single 552 * load/store instructions, integer and single
552 * precision floating point operations. 553 * precision floating point operations. Only check
554 * for NEON if the hardware has the MVFR registers.
553 */ 555 */
554 if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) 556 if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
555 elf_hwcap |= HWCAP_NEON; 557 if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
558 elf_hwcap |= HWCAP_NEON;
559 }
556#endif 560#endif
557 } 561 }
558 return 0; 562 return 0;