diff options
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r-- | arch/arm/vfp/vfpmodule.c | 93 |
1 files changed, 52 insertions, 41 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index 2f37e1d6cb45..5002d002f6e3 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -722,6 +722,7 @@ static int __init vfp_init(void) { unsigned int vfpsid; unsigned int cpu_arch = cpu_architecture(); + u32 mvfr0; if (cpu_arch >= CPU_ARCH_ARMv6) on_each_cpu(vfp_enable, NULL, 1); @@ -738,63 +739,73 @@ static int __init vfp_init(void) vfp_vector = vfp_null_entry; pr_info("VFP support v0.3: "); - if (VFP_arch) + if (VFP_arch) { pr_cont("not present\n"); - else if (vfpsid & FPSID_NODOUBLE) { - pr_cont("no double precision support\n"); - } else { - hotcpu_notifier(vfp_hotplug, 0); - - VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ - pr_cont("implementor %02x architecture %d part %02x variant %x rev %x\n", - (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, - (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT, - (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, - (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, - (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); - - vfp_vector = vfp_support_entry; - - thread_register_notifier(&vfp_notifier_block); - vfp_pm_init(); - + return 0; + /* Extract the architecture on CPUID scheme */ + } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { + VFP_arch = vfpsid & FPSID_CPUID_ARCH_MASK; + VFP_arch >>= FPSID_ARCH_BIT; /* - * We detected VFP, and the support code is - * in place; report VFP support to userspace. + * Check for the presence of the Advanced SIMD + * load/store instructions, integer and single + * precision floating point operations. Only check + * for NEON if the hardware has the MVFR registers. */ - elf_hwcap |= HWCAP_VFP; +#ifdef CONFIG_NEON + if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) + elf_hwcap |= HWCAP_NEON; +#endif #ifdef CONFIG_VFPv3 - if (VFP_arch >= 2) { + mvfr0 = fmrx(MVFR0); + if (((mvfr0 & MVFR0_DP_MASK) >> MVFR0_DP_BIT) == 0x2 || + ((mvfr0 & MVFR0_SP_MASK) >> MVFR0_SP_BIT) == 0x2) { elf_hwcap |= HWCAP_VFPv3; - /* * Check for VFPv3 D16 and VFPv4 D16. CPUs in * this configuration only have 16 x 64bit * registers. */ - if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) - elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ + if ((mvfr0 & MVFR0_A_SIMD_MASK) == 1) + /* also v4-D16 */ + elf_hwcap |= HWCAP_VFPv3D16; else elf_hwcap |= HWCAP_VFPD32; } + + if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) + elf_hwcap |= HWCAP_VFPv4; #endif - /* - * Check for the presence of the Advanced SIMD - * load/store instructions, integer and single - * precision floating point operations. Only check - * for NEON if the hardware has the MVFR registers. - */ - if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { -#ifdef CONFIG_NEON - if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) - elf_hwcap |= HWCAP_NEON; -#endif -#ifdef CONFIG_VFPv3 - if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000) - elf_hwcap |= HWCAP_VFPv4; -#endif + /* Extract the architecture version on pre-cpuid scheme */ + } else { + if (vfpsid & FPSID_NODOUBLE) { + pr_cont("no double precision support\n"); + return 0; } + + VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; } + + hotcpu_notifier(vfp_hotplug, 0); + + vfp_vector = vfp_support_entry; + + thread_register_notifier(&vfp_notifier_block); + vfp_pm_init(); + + /* + * We detected VFP, and the support code is + * in place; report VFP support to userspace. + */ + elf_hwcap |= HWCAP_VFP; + + pr_cont("implementor %02x architecture %d part %02x variant %x rev %x\n", + (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, + VFP_arch, + (vfpsid & FPSID_PART_MASK) >> FPSID_PART_BIT, + (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, + (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); + return 0; } |