diff options
author | Borislav Petkov <borislav.petkov@amd.com> | 2011-01-18 13:16:08 -0500 |
---|---|---|
committer | Borislav Petkov <borislav.petkov@amd.com> | 2011-03-17 09:46:24 -0400 |
commit | 41d8bfaba70311c2fa0666554ef160ea8ffc9daf (patch) | |
tree | 87b236d16240872304638ed0011bb2a9c244c0ee /drivers/edac/amd64_edac.c | |
parent | 5a5d237169152d4d7e4b6105eab15831829fb8e7 (diff) |
amd64_edac: Improve DRAM address mapping
Drop static tables which map the bits in F2x80 to a chip select size in
favor of functions doing the mapping with some bit fiddling. Also, add
F15 support.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac/amd64_edac.c')
-rw-r--r-- | drivers/edac/amd64_edac.c | 149 |
1 files changed, 81 insertions, 68 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index b85487d4de8d..eb6b6bace683 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -25,59 +25,12 @@ static struct mem_ctl_info **mcis; | |||
25 | static struct ecc_settings **ecc_stngs; | 25 | static struct ecc_settings **ecc_stngs; |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and | ||
29 | * later. | ||
30 | */ | ||
31 | static int ddr2_dbam_revCG[] = { | ||
32 | [0] = 32, | ||
33 | [1] = 64, | ||
34 | [2] = 128, | ||
35 | [3] = 256, | ||
36 | [4] = 512, | ||
37 | [5] = 1024, | ||
38 | [6] = 2048, | ||
39 | }; | ||
40 | |||
41 | static int ddr2_dbam_revD[] = { | ||
42 | [0] = 32, | ||
43 | [1] = 64, | ||
44 | [2 ... 3] = 128, | ||
45 | [4] = 256, | ||
46 | [5] = 512, | ||
47 | [6] = 256, | ||
48 | [7] = 512, | ||
49 | [8 ... 9] = 1024, | ||
50 | [10] = 2048, | ||
51 | }; | ||
52 | |||
53 | static int ddr2_dbam[] = { [0] = 128, | ||
54 | [1] = 256, | ||
55 | [2 ... 4] = 512, | ||
56 | [5 ... 6] = 1024, | ||
57 | [7 ... 8] = 2048, | ||
58 | [9 ... 10] = 4096, | ||
59 | [11] = 8192, | ||
60 | }; | ||
61 | |||
62 | static int ddr3_dbam[] = { [0] = -1, | ||
63 | [1] = 256, | ||
64 | [2] = 512, | ||
65 | [3 ... 4] = -1, | ||
66 | [5 ... 6] = 1024, | ||
67 | [7 ... 8] = 2048, | ||
68 | [9 ... 10] = 4096, | ||
69 | [11] = 8192, | ||
70 | }; | ||
71 | |||
72 | /* | ||
73 | * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing | 28 | * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing |
74 | * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching- | 29 | * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching- |
75 | * or higher value'. | 30 | * or higher value'. |
76 | * | 31 | * |
77 | *FIXME: Produce a better mapping/linearisation. | 32 | *FIXME: Produce a better mapping/linearisation. |
78 | */ | 33 | */ |
79 | |||
80 | |||
81 | struct scrubrate { | 34 | struct scrubrate { |
82 | u32 scrubval; /* bit pattern for scrub rate */ | 35 | u32 scrubval; /* bit pattern for scrub rate */ |
83 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ | 36 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ |
@@ -962,7 +915,7 @@ static int k8_early_channel_count(struct amd64_pvt *pvt) | |||
962 | 915 | ||
963 | if (pvt->ext_model >= K8_REV_F) | 916 | if (pvt->ext_model >= K8_REV_F) |
964 | /* RevF (NPT) and later */ | 917 | /* RevF (NPT) and later */ |
965 | flag = pvt->dclr0 & F10_WIDTH_128; | 918 | flag = pvt->dclr0 & WIDTH_128; |
966 | else | 919 | else |
967 | /* RevE and earlier */ | 920 | /* RevE and earlier */ |
968 | flag = pvt->dclr0 & REVE_WIDTH_128; | 921 | flag = pvt->dclr0 & REVE_WIDTH_128; |
@@ -1062,18 +1015,41 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, | |||
1062 | } | 1015 | } |
1063 | } | 1016 | } |
1064 | 1017 | ||
1065 | static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode) | 1018 | static int ddr2_cs_size(unsigned i, bool dct_width) |
1066 | { | 1019 | { |
1067 | int *dbam_map; | 1020 | unsigned shift = 0; |
1068 | 1021 | ||
1069 | if (pvt->ext_model >= K8_REV_F) | 1022 | if (i <= 2) |
1070 | dbam_map = ddr2_dbam; | 1023 | shift = i; |
1071 | else if (pvt->ext_model >= K8_REV_D) | 1024 | else if (!(i & 0x1)) |
1072 | dbam_map = ddr2_dbam_revD; | 1025 | shift = i >> 1; |
1073 | else | 1026 | else |
1074 | dbam_map = ddr2_dbam_revCG; | 1027 | shift = (i + 1) >> 1; |
1028 | |||
1029 | return 128 << (shift + !!dct_width); | ||
1030 | } | ||
1031 | |||
1032 | static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | ||
1033 | unsigned cs_mode) | ||
1034 | { | ||
1035 | u32 dclr = dct ? pvt->dclr1 : pvt->dclr0; | ||
1036 | |||
1037 | if (pvt->ext_model >= K8_REV_F) { | ||
1038 | WARN_ON(cs_mode > 11); | ||
1039 | return ddr2_cs_size(cs_mode, dclr & WIDTH_128); | ||
1040 | } | ||
1041 | else if (pvt->ext_model >= K8_REV_D) { | ||
1042 | WARN_ON(cs_mode > 10); | ||
1075 | 1043 | ||
1076 | return dbam_map[cs_mode]; | 1044 | if (cs_mode == 3 || cs_mode == 8) |
1045 | return 32 << (cs_mode - 1); | ||
1046 | else | ||
1047 | return 32 << cs_mode; | ||
1048 | } | ||
1049 | else { | ||
1050 | WARN_ON(cs_mode > 6); | ||
1051 | return 32 << cs_mode; | ||
1052 | } | ||
1077 | } | 1053 | } |
1078 | 1054 | ||
1079 | /* | 1055 | /* |
@@ -1089,7 +1065,7 @@ static int f1x_early_channel_count(struct amd64_pvt *pvt) | |||
1089 | int i, j, channels = 0; | 1065 | int i, j, channels = 0; |
1090 | 1066 | ||
1091 | /* On F10h, if we are in 128 bit mode, then we are using 2 channels */ | 1067 | /* On F10h, if we are in 128 bit mode, then we are using 2 channels */ |
1092 | if (boot_cpu_data.x86 == 0x10 && (pvt->dclr0 & F10_WIDTH_128)) | 1068 | if (boot_cpu_data.x86 == 0x10 && (pvt->dclr0 & WIDTH_128)) |
1093 | return 2; | 1069 | return 2; |
1094 | 1070 | ||
1095 | /* | 1071 | /* |
@@ -1126,16 +1102,50 @@ static int f1x_early_channel_count(struct amd64_pvt *pvt) | |||
1126 | return channels; | 1102 | return channels; |
1127 | } | 1103 | } |
1128 | 1104 | ||
1129 | static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode) | 1105 | static int ddr3_cs_size(unsigned i, bool dct_width) |
1106 | { | ||
1107 | unsigned shift = 0; | ||
1108 | int cs_size = 0; | ||
1109 | |||
1110 | if (i == 0 || i == 3 || i == 4) | ||
1111 | cs_size = -1; | ||
1112 | else if (i <= 2) | ||
1113 | shift = i; | ||
1114 | else if (i == 12) | ||
1115 | shift = 7; | ||
1116 | else if (!(i & 0x1)) | ||
1117 | shift = i >> 1; | ||
1118 | else | ||
1119 | shift = (i + 1) >> 1; | ||
1120 | |||
1121 | if (cs_size != -1) | ||
1122 | cs_size = (128 * (1 << !!dct_width)) << shift; | ||
1123 | |||
1124 | return cs_size; | ||
1125 | } | ||
1126 | |||
1127 | static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | ||
1128 | unsigned cs_mode) | ||
1130 | { | 1129 | { |
1131 | int *dbam_map; | 1130 | u32 dclr = dct ? pvt->dclr1 : pvt->dclr0; |
1131 | |||
1132 | WARN_ON(cs_mode > 11); | ||
1132 | 1133 | ||
1133 | if (pvt->dchr0 & DDR3_MODE || pvt->dchr1 & DDR3_MODE) | 1134 | if (pvt->dchr0 & DDR3_MODE || pvt->dchr1 & DDR3_MODE) |
1134 | dbam_map = ddr3_dbam; | 1135 | return ddr3_cs_size(cs_mode, dclr & WIDTH_128); |
1135 | else | 1136 | else |
1136 | dbam_map = ddr2_dbam; | 1137 | return ddr2_cs_size(cs_mode, dclr & WIDTH_128); |
1138 | } | ||
1139 | |||
1140 | /* | ||
1141 | * F15h supports only 64bit DCT interfaces | ||
1142 | */ | ||
1143 | static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | ||
1144 | unsigned cs_mode) | ||
1145 | { | ||
1146 | WARN_ON(cs_mode > 12); | ||
1137 | 1147 | ||
1138 | return dbam_map[cs_mode]; | 1148 | return ddr3_cs_size(cs_mode, false); |
1139 | } | 1149 | } |
1140 | 1150 | ||
1141 | static void read_dram_ctl_register(struct amd64_pvt *pvt) | 1151 | static void read_dram_ctl_register(struct amd64_pvt *pvt) |
@@ -1528,7 +1538,7 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) | |||
1528 | u32 dbam = ctrl ? pvt->dbam1 : pvt->dbam0; | 1538 | u32 dbam = ctrl ? pvt->dbam1 : pvt->dbam0; |
1529 | 1539 | ||
1530 | if (boot_cpu_data.x86 == 0xf) { | 1540 | if (boot_cpu_data.x86 == 0xf) { |
1531 | if (pvt->dclr0 & F10_WIDTH_128) | 1541 | if (pvt->dclr0 & WIDTH_128) |
1532 | factor = 1; | 1542 | factor = 1; |
1533 | 1543 | ||
1534 | /* K8 families < revF not supported yet */ | 1544 | /* K8 families < revF not supported yet */ |
@@ -1551,11 +1561,13 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) | |||
1551 | 1561 | ||
1552 | size0 = 0; | 1562 | size0 = 0; |
1553 | if (dcsb[dimm*2] & DCSB_CS_ENABLE) | 1563 | if (dcsb[dimm*2] & DCSB_CS_ENABLE) |
1554 | size0 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); | 1564 | size0 = pvt->ops->dbam_to_cs(pvt, ctrl, |
1565 | DBAM_DIMM(dimm, dbam)); | ||
1555 | 1566 | ||
1556 | size1 = 0; | 1567 | size1 = 0; |
1557 | if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE) | 1568 | if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE) |
1558 | size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); | 1569 | size1 = pvt->ops->dbam_to_cs(pvt, ctrl, |
1570 | DBAM_DIMM(dimm, dbam)); | ||
1559 | 1571 | ||
1560 | amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", | 1572 | amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", |
1561 | dimm * 2, size0 << factor, | 1573 | dimm * 2, size0 << factor, |
@@ -1591,6 +1603,7 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1591 | .ops = { | 1603 | .ops = { |
1592 | .early_channel_count = f1x_early_channel_count, | 1604 | .early_channel_count = f1x_early_channel_count, |
1593 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, | 1605 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, |
1606 | .dbam_to_cs = f15_dbam_to_chip_select, | ||
1594 | .read_dct_pci_cfg = f15_read_dct_pci_cfg, | 1607 | .read_dct_pci_cfg = f15_read_dct_pci_cfg, |
1595 | } | 1608 | } |
1596 | }, | 1609 | }, |
@@ -2030,7 +2043,7 @@ static void read_mc_regs(struct amd64_pvt *pvt) | |||
2030 | * encompasses | 2043 | * encompasses |
2031 | * | 2044 | * |
2032 | */ | 2045 | */ |
2033 | static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) | 2046 | static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) |
2034 | { | 2047 | { |
2035 | u32 cs_mode, nr_pages; | 2048 | u32 cs_mode, nr_pages; |
2036 | 2049 | ||
@@ -2043,7 +2056,7 @@ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) | |||
2043 | */ | 2056 | */ |
2044 | cs_mode = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF; | 2057 | cs_mode = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF; |
2045 | 2058 | ||
2046 | nr_pages = pvt->ops->dbam_to_cs(pvt, cs_mode) << (20 - PAGE_SHIFT); | 2059 | nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT); |
2047 | 2060 | ||
2048 | /* | 2061 | /* |
2049 | * If dual channel then double the memory size of single channel. | 2062 | * If dual channel then double the memory size of single channel. |
@@ -2091,7 +2104,7 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
2091 | i, pvt->mc_node_id); | 2104 | i, pvt->mc_node_id); |
2092 | 2105 | ||
2093 | empty = 0; | 2106 | empty = 0; |
2094 | csrow->nr_pages = amd64_csrow_nr_pages(i, pvt); | 2107 | csrow->nr_pages = amd64_csrow_nr_pages(pvt, 0, i); |
2095 | find_csrow_limits(mci, i, &input_addr_min, &input_addr_max); | 2108 | find_csrow_limits(mci, i, &input_addr_min, &input_addr_max); |
2096 | sys_addr = input_addr_to_sys_addr(mci, input_addr_min); | 2109 | sys_addr = input_addr_to_sys_addr(mci, input_addr_min); |
2097 | csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT); | 2110 | csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT); |