diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/edac/amd64_edac.c | 246 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 58 |
2 files changed, 270 insertions, 34 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 8b6a0343c220..a5d6348d591f 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -123,7 +123,7 @@ static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct) | |||
123 | u32 reg = 0; | 123 | u32 reg = 0; |
124 | 124 | ||
125 | amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); | 125 | amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); |
126 | reg &= 0xfffffffe; | 126 | reg &= (pvt->model >= 0x30) ? ~3 : ~1; |
127 | reg |= dct; | 127 | reg |= dct; |
128 | amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); | 128 | amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); |
129 | } | 129 | } |
@@ -133,8 +133,9 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, | |||
133 | { | 133 | { |
134 | u8 dct = 0; | 134 | u8 dct = 0; |
135 | 135 | ||
136 | /* For F15 M30h, the second dct is DCT 3, refer to BKDG Section 2.10 */ | ||
136 | if (addr >= 0x140 && addr <= 0x1a0) { | 137 | if (addr >= 0x140 && addr <= 0x1a0) { |
137 | dct = 1; | 138 | dct = (pvt->model >= 0x30) ? 3 : 1; |
138 | addr -= 0x100; | 139 | addr -= 0x100; |
139 | } | 140 | } |
140 | 141 | ||
@@ -205,8 +206,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) | |||
205 | if (boot_cpu_data.x86 == 0xf) | 206 | if (boot_cpu_data.x86 == 0xf) |
206 | min_scrubrate = 0x0; | 207 | min_scrubrate = 0x0; |
207 | 208 | ||
208 | /* F15h Erratum #505 */ | 209 | /* Erratum #505 for F15h Model 0x00 - Model 0x01, Stepping 0 */ |
209 | if (boot_cpu_data.x86 == 0x15) | 210 | if (boot_cpu_data.x86 == 0x15 && |
211 | boot_cpu_data.x86_model <= 0x01 && | ||
212 | boot_cpu_data.x86_mask < 0x1) | ||
210 | f15h_select_dct(pvt, 0); | 213 | f15h_select_dct(pvt, 0); |
211 | 214 | ||
212 | return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate); | 215 | return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate); |
@@ -218,8 +221,10 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci) | |||
218 | u32 scrubval = 0; | 221 | u32 scrubval = 0; |
219 | int i, retval = -EINVAL; | 222 | int i, retval = -EINVAL; |
220 | 223 | ||
221 | /* F15h Erratum #505 */ | 224 | /* Erratum #505 for F15h Model 0x00 - Model 0x01, Stepping 0 */ |
222 | if (boot_cpu_data.x86 == 0x15) | 225 | if (boot_cpu_data.x86 == 0x15 && |
226 | boot_cpu_data.x86_model <= 0x01 && | ||
227 | boot_cpu_data.x86_mask < 0x1) | ||
223 | f15h_select_dct(pvt, 0); | 228 | f15h_select_dct(pvt, 0); |
224 | 229 | ||
225 | amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); | 230 | amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); |
@@ -335,7 +340,7 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct, | |||
335 | u64 csbase, csmask, base_bits, mask_bits; | 340 | u64 csbase, csmask, base_bits, mask_bits; |
336 | u8 addr_shift; | 341 | u8 addr_shift; |
337 | 342 | ||
338 | if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) { | 343 | if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) { |
339 | csbase = pvt->csels[dct].csbases[csrow]; | 344 | csbase = pvt->csels[dct].csbases[csrow]; |
340 | csmask = pvt->csels[dct].csmasks[csrow]; | 345 | csmask = pvt->csels[dct].csmasks[csrow]; |
341 | base_bits = GENMASK(21, 31) | GENMASK(9, 15); | 346 | base_bits = GENMASK(21, 31) | GENMASK(9, 15); |
@@ -343,10 +348,11 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct, | |||
343 | addr_shift = 4; | 348 | addr_shift = 4; |
344 | 349 | ||
345 | /* | 350 | /* |
346 | * F16h needs two addr_shift values: 8 for high and 6 for low | 351 | * F16h and F15h, models 30h and later need two addr_shift values: |
347 | * (cf. F16h BKDG). | 352 | * 8 for high and 6 for low (cf. F16h BKDG). |
348 | */ | 353 | */ |
349 | } else if (boot_cpu_data.x86 == 0x16) { | 354 | } else if (pvt->fam == 0x16 || |
355 | (pvt->fam == 0x15 && pvt->model >= 0x30)) { | ||
350 | csbase = pvt->csels[dct].csbases[csrow]; | 356 | csbase = pvt->csels[dct].csbases[csrow]; |
351 | csmask = pvt->csels[dct].csmasks[csrow >> 1]; | 357 | csmask = pvt->csels[dct].csmasks[csrow >> 1]; |
352 | 358 | ||
@@ -736,13 +742,16 @@ static void dump_misc_regs(struct amd64_pvt *pvt) | |||
736 | } | 742 | } |
737 | 743 | ||
738 | /* | 744 | /* |
739 | * see BKDG, F2x[1,0][5C:40], F2[1,0][6C:60] | 745 | * See BKDG, F2x[1,0][5C:40], F2[1,0][6C:60] |
740 | */ | 746 | */ |
741 | static void prep_chip_selects(struct amd64_pvt *pvt) | 747 | static void prep_chip_selects(struct amd64_pvt *pvt) |
742 | { | 748 | { |
743 | if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) { | 749 | if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) { |
744 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; | 750 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; |
745 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8; | 751 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8; |
752 | } else if (pvt->fam == 0x15 && pvt->model >= 0x30) { | ||
753 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4; | ||
754 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2; | ||
746 | } else { | 755 | } else { |
747 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; | 756 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; |
748 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4; | 757 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4; |
@@ -916,15 +925,15 @@ static struct pci_dev *pci_get_related_function(unsigned int vendor, | |||
916 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | 925 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) |
917 | { | 926 | { |
918 | struct amd_northbridge *nb; | 927 | struct amd_northbridge *nb; |
919 | struct pci_dev *misc, *f1 = NULL; | 928 | struct pci_dev *f1 = NULL; |
920 | struct cpuinfo_x86 *c = &boot_cpu_data; | 929 | unsigned int pci_func; |
921 | int off = range << 3; | 930 | int off = range << 3; |
922 | u32 llim; | 931 | u32 llim; |
923 | 932 | ||
924 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); | 933 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); |
925 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); | 934 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); |
926 | 935 | ||
927 | if (c->x86 == 0xf) | 936 | if (pvt->fam == 0xf) |
928 | return; | 937 | return; |
929 | 938 | ||
930 | if (!dram_rw(pvt, range)) | 939 | if (!dram_rw(pvt, range)) |
@@ -934,15 +943,17 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | |||
934 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); | 943 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); |
935 | 944 | ||
936 | /* F15h: factor in CC6 save area by reading dst node's limit reg */ | 945 | /* F15h: factor in CC6 save area by reading dst node's limit reg */ |
937 | if (c->x86 != 0x15) | 946 | if (pvt->fam != 0x15) |
938 | return; | 947 | return; |
939 | 948 | ||
940 | nb = node_to_amd_nb(dram_dst_node(pvt, range)); | 949 | nb = node_to_amd_nb(dram_dst_node(pvt, range)); |
941 | if (WARN_ON(!nb)) | 950 | if (WARN_ON(!nb)) |
942 | return; | 951 | return; |
943 | 952 | ||
944 | misc = nb->misc; | 953 | pci_func = (pvt->model == 0x30) ? PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 |
945 | f1 = pci_get_related_function(misc->vendor, PCI_DEVICE_ID_AMD_15H_NB_F1, misc); | 954 | : PCI_DEVICE_ID_AMD_15H_NB_F1; |
955 | |||
956 | f1 = pci_get_related_function(nb->misc->vendor, pci_func, nb->misc); | ||
946 | if (WARN_ON(!f1)) | 957 | if (WARN_ON(!f1)) |
947 | return; | 958 | return; |
948 | 959 | ||
@@ -1173,7 +1184,7 @@ static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | |||
1173 | } | 1184 | } |
1174 | 1185 | ||
1175 | /* | 1186 | /* |
1176 | * F16h has only limited cs_modes | 1187 | * F16h and F15h model 30h have only limited cs_modes. |
1177 | */ | 1188 | */ |
1178 | static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | 1189 | static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, |
1179 | unsigned cs_mode) | 1190 | unsigned cs_mode) |
@@ -1218,6 +1229,29 @@ static void read_dram_ctl_register(struct amd64_pvt *pvt) | |||
1218 | } | 1229 | } |
1219 | 1230 | ||
1220 | /* | 1231 | /* |
1232 | * Determine channel (DCT) based on the interleaving mode (see F15h M30h BKDG, | ||
1233 | * 2.10.12 Memory Interleaving Modes). | ||
1234 | */ | ||
1235 | static u8 f15_m30h_determine_channel(struct amd64_pvt *pvt, u64 sys_addr, | ||
1236 | u8 intlv_en, int num_dcts_intlv, | ||
1237 | u32 dct_sel) | ||
1238 | { | ||
1239 | u8 channel = 0; | ||
1240 | u8 select; | ||
1241 | |||
1242 | if (!(intlv_en)) | ||
1243 | return (u8)(dct_sel); | ||
1244 | |||
1245 | if (num_dcts_intlv == 2) { | ||
1246 | select = (sys_addr >> 8) & 0x3; | ||
1247 | channel = select ? 0x3 : 0; | ||
1248 | } else if (num_dcts_intlv == 4) | ||
1249 | channel = (sys_addr >> 8) & 0x7; | ||
1250 | |||
1251 | return channel; | ||
1252 | } | ||
1253 | |||
1254 | /* | ||
1221 | * Determine channel (DCT) based on the interleaving mode: F10h BKDG, 2.8.9 Memory | 1255 | * Determine channel (DCT) based on the interleaving mode: F10h BKDG, 2.8.9 Memory |
1222 | * Interleaving Modes. | 1256 | * Interleaving Modes. |
1223 | */ | 1257 | */ |
@@ -1366,6 +1400,10 @@ static int f1x_lookup_addr_in_dct(u64 in_addr, u8 nid, u8 dct) | |||
1366 | (in_addr & cs_mask), (cs_base & cs_mask)); | 1400 | (in_addr & cs_mask), (cs_base & cs_mask)); |
1367 | 1401 | ||
1368 | if ((in_addr & cs_mask) == (cs_base & cs_mask)) { | 1402 | if ((in_addr & cs_mask) == (cs_base & cs_mask)) { |
1403 | if (pvt->fam == 0x15 && pvt->model >= 0x30) { | ||
1404 | cs_found = csrow; | ||
1405 | break; | ||
1406 | } | ||
1369 | cs_found = f10_process_possible_spare(pvt, dct, csrow); | 1407 | cs_found = f10_process_possible_spare(pvt, dct, csrow); |
1370 | 1408 | ||
1371 | edac_dbg(1, " MATCH csrow=%d\n", cs_found); | 1409 | edac_dbg(1, " MATCH csrow=%d\n", cs_found); |
@@ -1492,20 +1530,142 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range, | |||
1492 | return cs_found; | 1530 | return cs_found; |
1493 | } | 1531 | } |
1494 | 1532 | ||
1495 | static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr, | 1533 | static int f15_m30h_match_to_this_node(struct amd64_pvt *pvt, unsigned range, |
1496 | int *chan_sel) | 1534 | u64 sys_addr, int *chan_sel) |
1535 | { | ||
1536 | int cs_found = -EINVAL; | ||
1537 | int num_dcts_intlv = 0; | ||
1538 | u64 chan_addr, chan_offset; | ||
1539 | u64 dct_base, dct_limit; | ||
1540 | u32 dct_cont_base_reg, dct_cont_limit_reg, tmp; | ||
1541 | u8 channel, alias_channel, leg_mmio_hole, dct_sel, dct_offset_en; | ||
1542 | |||
1543 | u64 dhar_offset = f10_dhar_offset(pvt); | ||
1544 | u8 intlv_addr = dct_sel_interleave_addr(pvt); | ||
1545 | u8 node_id = dram_dst_node(pvt, range); | ||
1546 | u8 intlv_en = dram_intlv_en(pvt, range); | ||
1547 | |||
1548 | amd64_read_pci_cfg(pvt->F1, DRAM_CONT_BASE, &dct_cont_base_reg); | ||
1549 | amd64_read_pci_cfg(pvt->F1, DRAM_CONT_LIMIT, &dct_cont_limit_reg); | ||
1550 | |||
1551 | dct_offset_en = (u8) ((dct_cont_base_reg >> 3) & BIT(0)); | ||
1552 | dct_sel = (u8) ((dct_cont_base_reg >> 4) & 0x7); | ||
1553 | |||
1554 | edac_dbg(1, "(range %d) SystemAddr= 0x%llx Limit=0x%llx\n", | ||
1555 | range, sys_addr, get_dram_limit(pvt, range)); | ||
1556 | |||
1557 | if (!(get_dram_base(pvt, range) <= sys_addr) && | ||
1558 | !(get_dram_limit(pvt, range) >= sys_addr)) | ||
1559 | return -EINVAL; | ||
1560 | |||
1561 | if (dhar_valid(pvt) && | ||
1562 | dhar_base(pvt) <= sys_addr && | ||
1563 | sys_addr < BIT_64(32)) { | ||
1564 | amd64_warn("Huh? Address is in the MMIO hole: 0x%016llx\n", | ||
1565 | sys_addr); | ||
1566 | return -EINVAL; | ||
1567 | } | ||
1568 | |||
1569 | /* Verify sys_addr is within DCT Range. */ | ||
1570 | dct_base = (dct_sel_baseaddr(pvt) << 27); | ||
1571 | dct_limit = (((dct_cont_limit_reg >> 11) & 0x1FFF) << 27) | 0x7FFFFFF; | ||
1572 | |||
1573 | if (!(dct_cont_base_reg & BIT(0)) && | ||
1574 | !(dct_base <= sys_addr && dct_limit >= sys_addr)) | ||
1575 | return -EINVAL; | ||
1576 | |||
1577 | /* Verify number of dct's that participate in channel interleaving. */ | ||
1578 | num_dcts_intlv = (int) hweight8(intlv_en); | ||
1579 | |||
1580 | if (!(num_dcts_intlv % 2 == 0) || (num_dcts_intlv > 4)) | ||
1581 | return -EINVAL; | ||
1582 | |||
1583 | channel = f15_m30h_determine_channel(pvt, sys_addr, intlv_en, | ||
1584 | num_dcts_intlv, dct_sel); | ||
1585 | |||
1586 | /* Verify we stay within the MAX number of channels allowed */ | ||
1587 | if (channel > 4 || channel < 0) | ||
1588 | return -EINVAL; | ||
1589 | |||
1590 | leg_mmio_hole = (u8) (dct_cont_base_reg >> 1 & BIT(0)); | ||
1591 | |||
1592 | /* Get normalized DCT addr */ | ||
1593 | if (leg_mmio_hole && (sys_addr >= BIT_64(32))) | ||
1594 | chan_offset = dhar_offset; | ||
1595 | else | ||
1596 | chan_offset = dct_base; | ||
1597 | |||
1598 | chan_addr = sys_addr - chan_offset; | ||
1599 | |||
1600 | /* remove channel interleave */ | ||
1601 | if (num_dcts_intlv == 2) { | ||
1602 | if (intlv_addr == 0x4) | ||
1603 | chan_addr = ((chan_addr >> 9) << 8) | | ||
1604 | (chan_addr & 0xff); | ||
1605 | else if (intlv_addr == 0x5) | ||
1606 | chan_addr = ((chan_addr >> 10) << 9) | | ||
1607 | (chan_addr & 0x1ff); | ||
1608 | else | ||
1609 | return -EINVAL; | ||
1610 | |||
1611 | } else if (num_dcts_intlv == 4) { | ||
1612 | if (intlv_addr == 0x4) | ||
1613 | chan_addr = ((chan_addr >> 10) << 8) | | ||
1614 | (chan_addr & 0xff); | ||
1615 | else if (intlv_addr == 0x5) | ||
1616 | chan_addr = ((chan_addr >> 11) << 9) | | ||
1617 | (chan_addr & 0x1ff); | ||
1618 | else | ||
1619 | return -EINVAL; | ||
1620 | } | ||
1621 | |||
1622 | if (dct_offset_en) { | ||
1623 | amd64_read_pci_cfg(pvt->F1, | ||
1624 | DRAM_CONT_HIGH_OFF + (int) channel * 4, | ||
1625 | &tmp); | ||
1626 | chan_addr += ((tmp >> 11) & 0xfff) << 27; | ||
1627 | } | ||
1628 | |||
1629 | f15h_select_dct(pvt, channel); | ||
1630 | |||
1631 | edac_dbg(1, " Normalized DCT addr: 0x%llx\n", chan_addr); | ||
1632 | |||
1633 | /* | ||
1634 | * Find Chip select: | ||
1635 | * if channel = 3, then alias it to 1. This is because, in F15 M30h, | ||
1636 | * there is support for 4 DCT's, but only 2 are currently functional. | ||
1637 | * They are DCT0 and DCT3. But we have read all registers of DCT3 into | ||
1638 | * pvt->csels[1]. So we need to use '1' here to get correct info. | ||
1639 | * Refer F15 M30h BKDG Section 2.10 and 2.10.3 for clarifications. | ||
1640 | */ | ||
1641 | alias_channel = (channel == 3) ? 1 : channel; | ||
1642 | |||
1643 | cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, alias_channel); | ||
1644 | |||
1645 | if (cs_found >= 0) | ||
1646 | *chan_sel = alias_channel; | ||
1647 | |||
1648 | return cs_found; | ||
1649 | } | ||
1650 | |||
1651 | static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, | ||
1652 | u64 sys_addr, | ||
1653 | int *chan_sel) | ||
1497 | { | 1654 | { |
1498 | int cs_found = -EINVAL; | 1655 | int cs_found = -EINVAL; |
1499 | unsigned range; | 1656 | unsigned range; |
1500 | 1657 | ||
1501 | for (range = 0; range < DRAM_RANGES; range++) { | 1658 | for (range = 0; range < DRAM_RANGES; range++) { |
1502 | |||
1503 | if (!dram_rw(pvt, range)) | 1659 | if (!dram_rw(pvt, range)) |
1504 | continue; | 1660 | continue; |
1505 | 1661 | ||
1506 | if ((get_dram_base(pvt, range) <= sys_addr) && | 1662 | if (pvt->fam == 0x15 && pvt->model >= 0x30) |
1507 | (get_dram_limit(pvt, range) >= sys_addr)) { | 1663 | cs_found = f15_m30h_match_to_this_node(pvt, range, |
1664 | sys_addr, | ||
1665 | chan_sel); | ||
1508 | 1666 | ||
1667 | else if ((get_dram_base(pvt, range) <= sys_addr) && | ||
1668 | (get_dram_limit(pvt, range) >= sys_addr)) { | ||
1509 | cs_found = f1x_match_to_this_node(pvt, range, | 1669 | cs_found = f1x_match_to_this_node(pvt, range, |
1510 | sys_addr, chan_sel); | 1670 | sys_addr, chan_sel); |
1511 | if (cs_found >= 0) | 1671 | if (cs_found >= 0) |
@@ -1624,6 +1784,17 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1624 | .read_dct_pci_cfg = f15_read_dct_pci_cfg, | 1784 | .read_dct_pci_cfg = f15_read_dct_pci_cfg, |
1625 | } | 1785 | } |
1626 | }, | 1786 | }, |
1787 | [F15_M30H_CPUS] = { | ||
1788 | .ctl_name = "F15h_M30h", | ||
1789 | .f1_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1, | ||
1790 | .f3_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F3, | ||
1791 | .ops = { | ||
1792 | .early_channel_count = f1x_early_channel_count, | ||
1793 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, | ||
1794 | .dbam_to_cs = f16_dbam_to_chip_select, | ||
1795 | .read_dct_pci_cfg = f15_read_dct_pci_cfg, | ||
1796 | } | ||
1797 | }, | ||
1627 | [F16_CPUS] = { | 1798 | [F16_CPUS] = { |
1628 | .ctl_name = "F16h", | 1799 | .ctl_name = "F16h", |
1629 | .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, | 1800 | .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, |
@@ -2387,10 +2558,13 @@ static void setup_mci_misc_attrs(struct mem_ctl_info *mci, | |||
2387 | */ | 2558 | */ |
2388 | static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) | 2559 | static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) |
2389 | { | 2560 | { |
2390 | u8 fam = boot_cpu_data.x86; | ||
2391 | struct amd64_family_type *fam_type = NULL; | 2561 | struct amd64_family_type *fam_type = NULL; |
2392 | 2562 | ||
2393 | switch (fam) { | 2563 | pvt->ext_model = boot_cpu_data.x86_model >> 4; |
2564 | pvt->model = boot_cpu_data.x86_model; | ||
2565 | pvt->fam = boot_cpu_data.x86; | ||
2566 | |||
2567 | switch (pvt->fam) { | ||
2394 | case 0xf: | 2568 | case 0xf: |
2395 | fam_type = &amd64_family_types[K8_CPUS]; | 2569 | fam_type = &amd64_family_types[K8_CPUS]; |
2396 | pvt->ops = &amd64_family_types[K8_CPUS].ops; | 2570 | pvt->ops = &amd64_family_types[K8_CPUS].ops; |
@@ -2402,6 +2576,12 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) | |||
2402 | break; | 2576 | break; |
2403 | 2577 | ||
2404 | case 0x15: | 2578 | case 0x15: |
2579 | if (pvt->model == 0x30) { | ||
2580 | fam_type = &amd64_family_types[F15_M30H_CPUS]; | ||
2581 | pvt->ops = &amd64_family_types[F15_M30H_CPUS].ops; | ||
2582 | break; | ||
2583 | } | ||
2584 | |||
2405 | fam_type = &amd64_family_types[F15_CPUS]; | 2585 | fam_type = &amd64_family_types[F15_CPUS]; |
2406 | pvt->ops = &amd64_family_types[F15_CPUS].ops; | 2586 | pvt->ops = &amd64_family_types[F15_CPUS].ops; |
2407 | break; | 2587 | break; |
@@ -2416,10 +2596,8 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) | |||
2416 | return NULL; | 2596 | return NULL; |
2417 | } | 2597 | } |
2418 | 2598 | ||
2419 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | ||
2420 | |||
2421 | amd64_info("%s %sdetected (node %d).\n", fam_type->ctl_name, | 2599 | amd64_info("%s %sdetected (node %d).\n", fam_type->ctl_name, |
2422 | (fam == 0xf ? | 2600 | (pvt->fam == 0xf ? |
2423 | (pvt->ext_model >= K8_REV_F ? "revF or later " | 2601 | (pvt->ext_model >= K8_REV_F ? "revF or later " |
2424 | : "revE or earlier ") | 2602 | : "revE or earlier ") |
2425 | : ""), pvt->mc_node_id); | 2603 | : ""), pvt->mc_node_id); |
@@ -2638,6 +2816,14 @@ static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = { | |||
2638 | }, | 2816 | }, |
2639 | { | 2817 | { |
2640 | .vendor = PCI_VENDOR_ID_AMD, | 2818 | .vendor = PCI_VENDOR_ID_AMD, |
2819 | .device = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2, | ||
2820 | .subvendor = PCI_ANY_ID, | ||
2821 | .subdevice = PCI_ANY_ID, | ||
2822 | .class = 0, | ||
2823 | .class_mask = 0, | ||
2824 | }, | ||
2825 | { | ||
2826 | .vendor = PCI_VENDOR_ID_AMD, | ||
2641 | .device = PCI_DEVICE_ID_AMD_16H_NB_F2, | 2827 | .device = PCI_DEVICE_ID_AMD_16H_NB_F2, |
2642 | .subvendor = PCI_ANY_ID, | 2828 | .subvendor = PCI_ANY_ID, |
2643 | .subdevice = PCI_ANY_ID, | 2829 | .subdevice = PCI_ANY_ID, |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 2c6f113bae2b..8fddad7b3b95 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -170,6 +170,8 @@ | |||
170 | /* | 170 | /* |
171 | * PCI-defined configuration space registers | 171 | * PCI-defined configuration space registers |
172 | */ | 172 | */ |
173 | #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b | ||
174 | #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F2 0x141c | ||
173 | #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 | 175 | #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 |
174 | #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 | 176 | #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 |
175 | #define PCI_DEVICE_ID_AMD_16H_NB_F1 0x1531 | 177 | #define PCI_DEVICE_ID_AMD_16H_NB_F1 0x1531 |
@@ -181,13 +183,22 @@ | |||
181 | #define DRAM_BASE_LO 0x40 | 183 | #define DRAM_BASE_LO 0x40 |
182 | #define DRAM_LIMIT_LO 0x44 | 184 | #define DRAM_LIMIT_LO 0x44 |
183 | 185 | ||
184 | #define dram_intlv_en(pvt, i) ((u8)((pvt->ranges[i].base.lo >> 8) & 0x7)) | 186 | /* |
187 | * F15 M30h D18F1x2[1C:00] | ||
188 | */ | ||
189 | #define DRAM_CONT_BASE 0x200 | ||
190 | #define DRAM_CONT_LIMIT 0x204 | ||
191 | |||
192 | /* | ||
193 | * F15 M30h D18F1x2[4C:40] | ||
194 | */ | ||
195 | #define DRAM_CONT_HIGH_OFF 0x240 | ||
196 | |||
185 | #define dram_rw(pvt, i) ((u8)(pvt->ranges[i].base.lo & 0x3)) | 197 | #define dram_rw(pvt, i) ((u8)(pvt->ranges[i].base.lo & 0x3)) |
186 | #define dram_intlv_sel(pvt, i) ((u8)((pvt->ranges[i].lim.lo >> 8) & 0x7)) | 198 | #define dram_intlv_sel(pvt, i) ((u8)((pvt->ranges[i].lim.lo >> 8) & 0x7)) |
187 | #define dram_dst_node(pvt, i) ((u8)(pvt->ranges[i].lim.lo & 0x7)) | 199 | #define dram_dst_node(pvt, i) ((u8)(pvt->ranges[i].lim.lo & 0x7)) |
188 | 200 | ||
189 | #define DHAR 0xf0 | 201 | #define DHAR 0xf0 |
190 | #define dhar_valid(pvt) ((pvt)->dhar & BIT(0)) | ||
191 | #define dhar_mem_hoist_valid(pvt) ((pvt)->dhar & BIT(1)) | 202 | #define dhar_mem_hoist_valid(pvt) ((pvt)->dhar & BIT(1)) |
192 | #define dhar_base(pvt) ((pvt)->dhar & 0xff000000) | 203 | #define dhar_base(pvt) ((pvt)->dhar & 0xff000000) |
193 | #define k8_dhar_offset(pvt) (((pvt)->dhar & 0x0000ff00) << 16) | 204 | #define k8_dhar_offset(pvt) (((pvt)->dhar & 0x0000ff00) << 16) |
@@ -234,8 +245,6 @@ | |||
234 | #define DDR3_MODE BIT(8) | 245 | #define DDR3_MODE BIT(8) |
235 | 246 | ||
236 | #define DCT_SEL_LO 0x110 | 247 | #define DCT_SEL_LO 0x110 |
237 | #define dct_sel_baseaddr(pvt) ((pvt)->dct_sel_lo & 0xFFFFF800) | ||
238 | #define dct_sel_interleave_addr(pvt) (((pvt)->dct_sel_lo >> 6) & 0x3) | ||
239 | #define dct_high_range_enabled(pvt) ((pvt)->dct_sel_lo & BIT(0)) | 248 | #define dct_high_range_enabled(pvt) ((pvt)->dct_sel_lo & BIT(0)) |
240 | #define dct_interleave_enabled(pvt) ((pvt)->dct_sel_lo & BIT(2)) | 249 | #define dct_interleave_enabled(pvt) ((pvt)->dct_sel_lo & BIT(2)) |
241 | 250 | ||
@@ -297,6 +306,7 @@ enum amd_families { | |||
297 | K8_CPUS = 0, | 306 | K8_CPUS = 0, |
298 | F10_CPUS, | 307 | F10_CPUS, |
299 | F15_CPUS, | 308 | F15_CPUS, |
309 | F15_M30H_CPUS, | ||
300 | F16_CPUS, | 310 | F16_CPUS, |
301 | NUM_FAMILIES, | 311 | NUM_FAMILIES, |
302 | }; | 312 | }; |
@@ -337,6 +347,8 @@ struct amd64_pvt { | |||
337 | struct pci_dev *F1, *F2, *F3; | 347 | struct pci_dev *F1, *F2, *F3; |
338 | 348 | ||
339 | u16 mc_node_id; /* MC index of this MC node */ | 349 | u16 mc_node_id; /* MC index of this MC node */ |
350 | u8 fam; /* CPU family */ | ||
351 | u8 model; /* CPU model */ | ||
340 | int ext_model; /* extended model value of this node */ | 352 | int ext_model; /* extended model value of this node */ |
341 | int channel_count; | 353 | int channel_count; |
342 | 354 | ||
@@ -414,6 +426,14 @@ static inline u16 extract_syndrome(u64 status) | |||
414 | return ((status >> 47) & 0xff) | ((status >> 16) & 0xff00); | 426 | return ((status >> 47) & 0xff) | ((status >> 16) & 0xff00); |
415 | } | 427 | } |
416 | 428 | ||
429 | static inline u8 dct_sel_interleave_addr(struct amd64_pvt *pvt) | ||
430 | { | ||
431 | if (pvt->fam == 0x15 && pvt->model >= 0x30) | ||
432 | return (((pvt->dct_sel_hi >> 9) & 0x1) << 2) | | ||
433 | ((pvt->dct_sel_lo >> 6) & 0x3); | ||
434 | |||
435 | return ((pvt)->dct_sel_lo >> 6) & 0x3; | ||
436 | } | ||
417 | /* | 437 | /* |
418 | * per-node ECC settings descriptor | 438 | * per-node ECC settings descriptor |
419 | */ | 439 | */ |
@@ -504,3 +524,33 @@ static inline void enable_caches(void *dummy) | |||
504 | { | 524 | { |
505 | write_cr0(read_cr0() & ~X86_CR0_CD); | 525 | write_cr0(read_cr0() & ~X86_CR0_CD); |
506 | } | 526 | } |
527 | |||
528 | static inline u8 dram_intlv_en(struct amd64_pvt *pvt, unsigned int i) | ||
529 | { | ||
530 | if (pvt->fam == 0x15 && pvt->model >= 0x30) { | ||
531 | u32 tmp; | ||
532 | amd64_read_pci_cfg(pvt->F1, DRAM_CONT_LIMIT, &tmp); | ||
533 | return (u8) tmp & 0xF; | ||
534 | } | ||
535 | return (u8) (pvt->ranges[i].base.lo >> 8) & 0x7; | ||
536 | } | ||
537 | |||
538 | static inline u8 dhar_valid(struct amd64_pvt *pvt) | ||
539 | { | ||
540 | if (pvt->fam == 0x15 && pvt->model >= 0x30) { | ||
541 | u32 tmp; | ||
542 | amd64_read_pci_cfg(pvt->F1, DRAM_CONT_BASE, &tmp); | ||
543 | return (tmp >> 1) & BIT(0); | ||
544 | } | ||
545 | return (pvt)->dhar & BIT(0); | ||
546 | } | ||
547 | |||
548 | static inline u32 dct_sel_baseaddr(struct amd64_pvt *pvt) | ||
549 | { | ||
550 | if (pvt->fam == 0x15 && pvt->model >= 0x30) { | ||
551 | u32 tmp; | ||
552 | amd64_read_pci_cfg(pvt->F1, DRAM_CONT_BASE, &tmp); | ||
553 | return (tmp >> 11) & 0x1FFF; | ||
554 | } | ||
555 | return (pvt)->dct_sel_lo & 0xFFFFF800; | ||
556 | } | ||