|
@@ -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;
|
|
|
}
|
|
|
|