diff options
Diffstat (limited to 'drivers/edac/mpc85xx_edac.c')
-rw-r--r-- | drivers/edac/mpc85xx_edac.c | 146 |
1 files changed, 138 insertions, 8 deletions
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 6d0114a1b77..517042fafa7 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -668,6 +668,111 @@ static struct of_platform_driver mpc85xx_l2_err_driver = { | |||
668 | 668 | ||
669 | /**************************** MC Err device ***************************/ | 669 | /**************************** MC Err device ***************************/ |
670 | 670 | ||
671 | /* | ||
672 | * Taken from table 8-55 in the MPC8641 User's Manual and/or 9-61 in the | ||
673 | * MPC8572 User's Manual. Each line represents a syndrome bit column as a | ||
674 | * 64-bit value, but split into an upper and lower 32-bit chunk. The labels | ||
675 | * below correspond to Freescale's manuals. | ||
676 | */ | ||
677 | static unsigned int ecc_table[16] = { | ||
678 | /* MSB LSB */ | ||
679 | /* [0:31] [32:63] */ | ||
680 | 0xf00fe11e, 0xc33c0ff7, /* Syndrome bit 7 */ | ||
681 | 0x00ff00ff, 0x00fff0ff, | ||
682 | 0x0f0f0f0f, 0x0f0fff00, | ||
683 | 0x11113333, 0x7777000f, | ||
684 | 0x22224444, 0x8888222f, | ||
685 | 0x44448888, 0xffff4441, | ||
686 | 0x8888ffff, 0x11118882, | ||
687 | 0xffff1111, 0x22221114, /* Syndrome bit 0 */ | ||
688 | }; | ||
689 | |||
690 | /* | ||
691 | * Calculate the correct ECC value for a 64-bit value specified by high:low | ||
692 | */ | ||
693 | static u8 calculate_ecc(u32 high, u32 low) | ||
694 | { | ||
695 | u32 mask_low; | ||
696 | u32 mask_high; | ||
697 | int bit_cnt; | ||
698 | u8 ecc = 0; | ||
699 | int i; | ||
700 | int j; | ||
701 | |||
702 | for (i = 0; i < 8; i++) { | ||
703 | mask_high = ecc_table[i * 2]; | ||
704 | mask_low = ecc_table[i * 2 + 1]; | ||
705 | bit_cnt = 0; | ||
706 | |||
707 | for (j = 0; j < 32; j++) { | ||
708 | if ((mask_high >> j) & 1) | ||
709 | bit_cnt ^= (high >> j) & 1; | ||
710 | if ((mask_low >> j) & 1) | ||
711 | bit_cnt ^= (low >> j) & 1; | ||
712 | } | ||
713 | |||
714 | ecc |= bit_cnt << i; | ||
715 | } | ||
716 | |||
717 | return ecc; | ||
718 | } | ||
719 | |||
720 | /* | ||
721 | * Create the syndrome code which is generated if the data line specified by | ||
722 | * 'bit' failed. Eg generate an 8-bit codes seen in Table 8-55 in the MPC8641 | ||
723 | * User's Manual and 9-61 in the MPC8572 User's Manual. | ||
724 | */ | ||
725 | static u8 syndrome_from_bit(unsigned int bit) { | ||
726 | int i; | ||
727 | u8 syndrome = 0; | ||
728 | |||
729 | /* | ||
730 | * Cycle through the upper or lower 32-bit portion of each value in | ||
731 | * ecc_table depending on if 'bit' is in the upper or lower half of | ||
732 | * 64-bit data. | ||
733 | */ | ||
734 | for (i = bit < 32; i < 16; i += 2) | ||
735 | syndrome |= ((ecc_table[i] >> (bit % 32)) & 1) << (i / 2); | ||
736 | |||
737 | return syndrome; | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | * Decode data and ecc syndrome to determine what went wrong | ||
742 | * Note: This can only decode single-bit errors | ||
743 | */ | ||
744 | static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc, | ||
745 | int *bad_data_bit, int *bad_ecc_bit) | ||
746 | { | ||
747 | int i; | ||
748 | u8 syndrome; | ||
749 | |||
750 | *bad_data_bit = -1; | ||
751 | *bad_ecc_bit = -1; | ||
752 | |||
753 | /* | ||
754 | * Calculate the ECC of the captured data and XOR it with the captured | ||
755 | * ECC to find an ECC syndrome value we can search for | ||
756 | */ | ||
757 | syndrome = calculate_ecc(cap_high, cap_low) ^ cap_ecc; | ||
758 | |||
759 | /* Check if a data line is stuck... */ | ||
760 | for (i = 0; i < 64; i++) { | ||
761 | if (syndrome == syndrome_from_bit(i)) { | ||
762 | *bad_data_bit = i; | ||
763 | return; | ||
764 | } | ||
765 | } | ||
766 | |||
767 | /* If data is correct, check ECC bits for errors... */ | ||
768 | for (i = 0; i < 8; i++) { | ||
769 | if ((syndrome >> i) & 0x1) { | ||
770 | *bad_ecc_bit = i; | ||
771 | return; | ||
772 | } | ||
773 | } | ||
774 | } | ||
775 | |||
671 | static void mpc85xx_mc_check(struct mem_ctl_info *mci) | 776 | static void mpc85xx_mc_check(struct mem_ctl_info *mci) |
672 | { | 777 | { |
673 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | 778 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; |
@@ -678,6 +783,10 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) | |||
678 | u32 err_addr; | 783 | u32 err_addr; |
679 | u32 pfn; | 784 | u32 pfn; |
680 | int row_index; | 785 | int row_index; |
786 | u32 cap_high; | ||
787 | u32 cap_low; | ||
788 | int bad_data_bit; | ||
789 | int bad_ecc_bit; | ||
681 | 790 | ||
682 | err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); | 791 | err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); |
683 | if (!err_detect) | 792 | if (!err_detect) |
@@ -711,14 +820,35 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci) | |||
711 | break; | 820 | break; |
712 | } | 821 | } |
713 | 822 | ||
714 | mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data High: %#8.8x\n", | 823 | cap_high = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_HI); |
715 | in_be32(pdata->mc_vbase + | 824 | cap_low = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_LO); |
716 | MPC85XX_MC_CAPTURE_DATA_HI)); | 825 | |
717 | mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data Low: %#8.8x\n", | 826 | /* |
718 | in_be32(pdata->mc_vbase + | 827 | * Analyze single-bit errors on 64-bit wide buses |
719 | MPC85XX_MC_CAPTURE_DATA_LO)); | 828 | * TODO: Add support for 32-bit wide buses |
720 | mpc85xx_mc_printk(mci, KERN_ERR, "syndrome: %#2.2x\n", syndrome); | 829 | */ |
721 | mpc85xx_mc_printk(mci, KERN_ERR, "err addr: %#8.8x\n", err_addr); | 830 | if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) { |
831 | sbe_ecc_decode(cap_high, cap_low, syndrome, | ||
832 | &bad_data_bit, &bad_ecc_bit); | ||
833 | |||
834 | if (bad_data_bit != -1) | ||
835 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
836 | "Faulty Data bit: %d\n", bad_data_bit); | ||
837 | if (bad_ecc_bit != -1) | ||
838 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
839 | "Faulty ECC bit: %d\n", bad_ecc_bit); | ||
840 | |||
841 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
842 | "Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n", | ||
843 | cap_high ^ (1 << (bad_data_bit - 32)), | ||
844 | cap_low ^ (1 << bad_data_bit), | ||
845 | syndrome ^ (1 << bad_ecc_bit)); | ||
846 | } | ||
847 | |||
848 | mpc85xx_mc_printk(mci, KERN_ERR, | ||
849 | "Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n", | ||
850 | cap_high, cap_low, syndrome); | ||
851 | mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8x\n", err_addr); | ||
722 | mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn); | 852 | mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn); |
723 | 853 | ||
724 | /* we are out of range */ | 854 | /* we are out of range */ |