diff options
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 2 | ||||
-rw-r--r-- | arch/powerpc/math-emu/math_efp.c | 53 |
2 files changed, 54 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index bd0d36e1c945..1bc6a12f3725 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -862,6 +862,8 @@ | |||
862 | #define PVR_7450 0x80000000 | 862 | #define PVR_7450 0x80000000 |
863 | #define PVR_8540 0x80200000 | 863 | #define PVR_8540 0x80200000 |
864 | #define PVR_8560 0x80200000 | 864 | #define PVR_8560 0x80200000 |
865 | #define PVR_VER_E500V1 0x8020 | ||
866 | #define PVR_VER_E500V2 0x8021 | ||
865 | /* | 867 | /* |
866 | * For the 8xx processors, all of them report the same PVR family for | 868 | * For the 8xx processors, all of them report the same PVR family for |
867 | * the PowerPC core. The various versions of these processors must be | 869 | * the PowerPC core. The various versions of these processors must be |
diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c index 41f4ef30e480..634830bdc0be 100644 --- a/arch/powerpc/math-emu/math_efp.c +++ b/arch/powerpc/math-emu/math_efp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/powerpc/math-emu/math_efp.c | 2 | * arch/powerpc/math-emu/math_efp.c |
3 | * | 3 | * |
4 | * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved. | 4 | * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc. |
5 | * | 5 | * |
6 | * Author: Ebony Zhu, <ebony.zhu@freescale.com> | 6 | * Author: Ebony Zhu, <ebony.zhu@freescale.com> |
7 | * Yu Liu, <yu.liu@freescale.com> | 7 | * Yu Liu, <yu.liu@freescale.com> |
@@ -104,6 +104,8 @@ | |||
104 | #define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \ | 104 | #define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \ |
105 | FP_EX_UNDERFLOW | FP_EX_OVERFLOW) | 105 | FP_EX_UNDERFLOW | FP_EX_OVERFLOW) |
106 | 106 | ||
107 | static int have_e500_cpu_a005_erratum; | ||
108 | |||
107 | union dw_union { | 109 | union dw_union { |
108 | u64 dp[1]; | 110 | u64 dp[1]; |
109 | u32 wp[2]; | 111 | u32 wp[2]; |
@@ -652,6 +654,15 @@ update_regs: | |||
652 | return 0; | 654 | return 0; |
653 | 655 | ||
654 | illegal: | 656 | illegal: |
657 | if (have_e500_cpu_a005_erratum) { | ||
658 | /* according to e500 cpu a005 erratum, reissue efp inst */ | ||
659 | regs->nip -= 4; | ||
660 | #ifdef DEBUG | ||
661 | printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn); | ||
662 | #endif | ||
663 | return 0; | ||
664 | } | ||
665 | |||
655 | printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn); | 666 | printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn); |
656 | return -ENOSYS; | 667 | return -ENOSYS; |
657 | } | 668 | } |
@@ -718,3 +729,43 @@ int speround_handler(struct pt_regs *regs) | |||
718 | 729 | ||
719 | return 0; | 730 | return 0; |
720 | } | 731 | } |
732 | |||
733 | int __init spe_mathemu_init(void) | ||
734 | { | ||
735 | u32 pvr, maj, min; | ||
736 | |||
737 | pvr = mfspr(SPRN_PVR); | ||
738 | |||
739 | if ((PVR_VER(pvr) == PVR_VER_E500V1) || | ||
740 | (PVR_VER(pvr) == PVR_VER_E500V2)) { | ||
741 | maj = PVR_MAJ(pvr); | ||
742 | min = PVR_MIN(pvr); | ||
743 | |||
744 | /* | ||
745 | * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1 | ||
746 | * need cpu a005 errata workaround | ||
747 | */ | ||
748 | switch (maj) { | ||
749 | case 1: | ||
750 | if (min < 1) | ||
751 | have_e500_cpu_a005_erratum = 1; | ||
752 | break; | ||
753 | case 2: | ||
754 | if (min < 3) | ||
755 | have_e500_cpu_a005_erratum = 1; | ||
756 | break; | ||
757 | case 3: | ||
758 | case 4: | ||
759 | case 5: | ||
760 | if (min < 1) | ||
761 | have_e500_cpu_a005_erratum = 1; | ||
762 | break; | ||
763 | default: | ||
764 | break; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | module_init(spe_mathemu_init); | ||