aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/amd64_edac.c
diff options
context:
space:
mode:
authorDoug Thompson <dougthompson@xmission.com>2009-04-27 10:12:00 -0400
committerBorislav Petkov <borislav.petkov@amd.com>2009-06-10 06:18:53 -0400
commit94be4bff21990674ac418c970c708a1a01cf709f (patch)
tree35eea3c55f5ef344e3ac0417970bfbb8891b8f71 /drivers/edac/amd64_edac.c
parent2da11654ea4d32c5700693675dfbd55c70619519 (diff)
amd64_edac: assign DRAM chip select base and mask in a family-specific way
Borislav: - cleanup/fix comments - fix function return value patterns - cleanup debug calls Reviewed-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: Doug Thompson <dougthompson@xmission.com> Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac/amd64_edac.c')
-rw-r--r--drivers/edac/amd64_edac.c142
1 files changed, 142 insertions, 0 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 3d6d0007ed5d..5ec44a440d65 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -871,3 +871,145 @@ err_reg:
871 debugf0("Error reading F2x%03x.\n", reg); 871 debugf0("Error reading F2x%03x.\n", reg);
872} 872}
873 873
874/*
875 * NOTE: CPU Revision Dependent code: Rev E and Rev F
876 *
877 * Set the DCSB and DCSM mask values depending on the CPU revision value. Also
878 * set the shift factor for the DCSB and DCSM values.
879 *
880 * ->dcs_mask_notused, RevE:
881 *
882 * To find the max InputAddr for the csrow, start with the base address and set
883 * all bits that are "don't care" bits in the test at the start of section
884 * 3.5.4 (p. 84).
885 *
886 * The "don't care" bits are all set bits in the mask and all bits in the gaps
887 * between bit ranges [35:25] and [19:13]. The value REV_E_DCS_NOTUSED_BITS
888 * represents bits [24:20] and [12:0], which are all bits in the above-mentioned
889 * gaps.
890 *
891 * ->dcs_mask_notused, RevF and later:
892 *
893 * To find the max InputAddr for the csrow, start with the base address and set
894 * all bits that are "don't care" bits in the test at the start of NPT section
895 * 4.5.4 (p. 87).
896 *
897 * The "don't care" bits are all set bits in the mask and all bits in the gaps
898 * between bit ranges [36:27] and [21:13].
899 *
900 * The value REV_F_F1Xh_DCS_NOTUSED_BITS represents bits [26:22] and [12:0],
901 * which are all bits in the above-mentioned gaps.
902 */
903static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt)
904{
905 if (pvt->ext_model >= OPTERON_CPU_REV_F) {
906 pvt->dcsb_base = REV_F_F1Xh_DCSB_BASE_BITS;
907 pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS;
908 pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS;
909 pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT;
910
911 switch (boot_cpu_data.x86) {
912 case 0xf:
913 pvt->num_dcsm = REV_F_DCSM_COUNT;
914 break;
915
916 case 0x10:
917 pvt->num_dcsm = F10_DCSM_COUNT;
918 break;
919
920 case 0x11:
921 pvt->num_dcsm = F11_DCSM_COUNT;
922 break;
923
924 default:
925 amd64_printk(KERN_ERR, "Unsupported family!\n");
926 break;
927 }
928 } else {
929 pvt->dcsb_base = REV_E_DCSB_BASE_BITS;
930 pvt->dcsm_mask = REV_E_DCSM_MASK_BITS;
931 pvt->dcs_mask_notused = REV_E_DCS_NOTUSED_BITS;
932 pvt->dcs_shift = REV_E_DCS_SHIFT;
933 pvt->num_dcsm = REV_E_DCSM_COUNT;
934 }
935}
936
937/*
938 * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask hw registers
939 */
940static void amd64_read_dct_base_mask(struct amd64_pvt *pvt)
941{
942 int cs, reg, err = 0;
943
944 amd64_set_dct_base_and_mask(pvt);
945
946 for (cs = 0; cs < CHIPSELECT_COUNT; cs++) {
947 reg = K8_DCSB0 + (cs * 4);
948 err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
949 &pvt->dcsb0[cs]);
950 if (unlikely(err))
951 debugf0("Reading K8_DCSB0[%d] failed\n", cs);
952 else
953 debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n",
954 cs, pvt->dcsb0[cs], reg);
955
956 /* If DCT are NOT ganged, then read in DCT1's base */
957 if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
958 reg = F10_DCSB1 + (cs * 4);
959 err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
960 &pvt->dcsb1[cs]);
961 if (unlikely(err))
962 debugf0("Reading F10_DCSB1[%d] failed\n", cs);
963 else
964 debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n",
965 cs, pvt->dcsb1[cs], reg);
966 } else {
967 pvt->dcsb1[cs] = 0;
968 }
969 }
970
971 for (cs = 0; cs < pvt->num_dcsm; cs++) {
972 reg = K8_DCSB0 + (cs * 4);
973 err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
974 &pvt->dcsm0[cs]);
975 if (unlikely(err))
976 debugf0("Reading K8_DCSM0 failed\n");
977 else
978 debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n",
979 cs, pvt->dcsm0[cs], reg);
980
981 /* If DCT are NOT ganged, then read in DCT1's mask */
982 if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
983 reg = F10_DCSM1 + (cs * 4);
984 err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
985 &pvt->dcsm1[cs]);
986 if (unlikely(err))
987 debugf0("Reading F10_DCSM1[%d] failed\n", cs);
988 else
989 debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n",
990 cs, pvt->dcsm1[cs], reg);
991 } else
992 pvt->dcsm1[cs] = 0;
993 }
994}
995
996static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt)
997{
998 enum mem_type type;
999
1000 if (boot_cpu_data.x86 >= 0x10 || pvt->ext_model >= OPTERON_CPU_REV_F) {
1001 /* Rev F and later */
1002 type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2;
1003 } else {
1004 /* Rev E and earlier */
1005 type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR;
1006 }
1007
1008 debugf1(" Memory type is: %s\n",
1009 (type == MEM_DDR2) ? "MEM_DDR2" :
1010 (type == MEM_RDDR2) ? "MEM_RDDR2" :
1011 (type == MEM_DDR) ? "MEM_DDR" : "MEM_RDDR");
1012
1013 return type;
1014}
1015