diff options
author | Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com> | 2013-04-17 15:57:13 -0400 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2013-04-19 06:46:50 -0400 |
commit | 94c1acf2c85b03a59a42d931a94a13a76c123a62 (patch) | |
tree | f5cb13964ea32a41486f48ba450a4d3f495cdbf7 /drivers/edac | |
parent | 41ef2d5678d83af030125550329b6ae8b74618fa (diff) |
amd64_edac: Add Family 16h support
Add code to handle DRAM ECC errors decoding for Fam16h.
Tested on Fam16h with ECC turned on using the mce_amd_inj facility and
works fine.
Signed-off-by: Aravind Gopalakrishnan <Aravind.Gopalakrishnan@amd.com>
[ Boris: cleanups and clarifications ]
Signed-off-by: Borislav Petkov <bp@suse.de>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/amd64_edac.c | 65 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 4 |
2 files changed, 67 insertions, 2 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e1d13c463c90..8b6a0343c220 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -98,6 +98,7 @@ int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset, | |||
98 | * | 98 | * |
99 | * F15h: we select which DCT we access using F1x10C[DctCfgSel] | 99 | * F15h: we select which DCT we access using F1x10C[DctCfgSel] |
100 | * | 100 | * |
101 | * F16h: has only 1 DCT | ||
101 | */ | 102 | */ |
102 | static int k8_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, | 103 | static int k8_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, |
103 | const char *func) | 104 | const char *func) |
@@ -340,6 +341,27 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct, | |||
340 | base_bits = GENMASK(21, 31) | GENMASK(9, 15); | 341 | base_bits = GENMASK(21, 31) | GENMASK(9, 15); |
341 | mask_bits = GENMASK(21, 29) | GENMASK(9, 15); | 342 | mask_bits = GENMASK(21, 29) | GENMASK(9, 15); |
342 | addr_shift = 4; | 343 | addr_shift = 4; |
344 | |||
345 | /* | ||
346 | * F16h needs two addr_shift values: 8 for high and 6 for low | ||
347 | * (cf. F16h BKDG). | ||
348 | */ | ||
349 | } else if (boot_cpu_data.x86 == 0x16) { | ||
350 | csbase = pvt->csels[dct].csbases[csrow]; | ||
351 | csmask = pvt->csels[dct].csmasks[csrow >> 1]; | ||
352 | |||
353 | *base = (csbase & GENMASK(5, 15)) << 6; | ||
354 | *base |= (csbase & GENMASK(19, 30)) << 8; | ||
355 | |||
356 | *mask = ~0ULL; | ||
357 | /* poke holes for the csmask */ | ||
358 | *mask &= ~((GENMASK(5, 15) << 6) | | ||
359 | (GENMASK(19, 30) << 8)); | ||
360 | |||
361 | *mask |= (csmask & GENMASK(5, 15)) << 6; | ||
362 | *mask |= (csmask & GENMASK(19, 30)) << 8; | ||
363 | |||
364 | return; | ||
343 | } else { | 365 | } else { |
344 | csbase = pvt->csels[dct].csbases[csrow]; | 366 | csbase = pvt->csels[dct].csbases[csrow]; |
345 | csmask = pvt->csels[dct].csmasks[csrow >> 1]; | 367 | csmask = pvt->csels[dct].csmasks[csrow >> 1]; |
@@ -1150,6 +1172,21 @@ static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | |||
1150 | return ddr3_cs_size(cs_mode, false); | 1172 | return ddr3_cs_size(cs_mode, false); |
1151 | } | 1173 | } |
1152 | 1174 | ||
1175 | /* | ||
1176 | * F16h has only limited cs_modes | ||
1177 | */ | ||
1178 | static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | ||
1179 | unsigned cs_mode) | ||
1180 | { | ||
1181 | WARN_ON(cs_mode > 12); | ||
1182 | |||
1183 | if (cs_mode == 6 || cs_mode == 8 || | ||
1184 | cs_mode == 9 || cs_mode == 12) | ||
1185 | return -1; | ||
1186 | else | ||
1187 | return ddr3_cs_size(cs_mode, false); | ||
1188 | } | ||
1189 | |||
1153 | static void read_dram_ctl_register(struct amd64_pvt *pvt) | 1190 | static void read_dram_ctl_register(struct amd64_pvt *pvt) |
1154 | { | 1191 | { |
1155 | 1192 | ||
@@ -1587,6 +1624,17 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1587 | .read_dct_pci_cfg = f15_read_dct_pci_cfg, | 1624 | .read_dct_pci_cfg = f15_read_dct_pci_cfg, |
1588 | } | 1625 | } |
1589 | }, | 1626 | }, |
1627 | [F16_CPUS] = { | ||
1628 | .ctl_name = "F16h", | ||
1629 | .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, | ||
1630 | .f3_id = PCI_DEVICE_ID_AMD_16H_NB_F3, | ||
1631 | .ops = { | ||
1632 | .early_channel_count = f1x_early_channel_count, | ||
1633 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, | ||
1634 | .dbam_to_cs = f16_dbam_to_chip_select, | ||
1635 | .read_dct_pci_cfg = f10_read_dct_pci_cfg, | ||
1636 | } | ||
1637 | }, | ||
1590 | }; | 1638 | }; |
1591 | 1639 | ||
1592 | /* | 1640 | /* |
@@ -1939,7 +1987,9 @@ static void read_mc_regs(struct amd64_pvt *pvt) | |||
1939 | 1987 | ||
1940 | if (c->x86 >= 0x10) { | 1988 | if (c->x86 >= 0x10) { |
1941 | amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); | 1989 | amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); |
1942 | amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1); | 1990 | if (c->x86 != 0x16) |
1991 | /* F16h has only DCT0 */ | ||
1992 | amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1); | ||
1943 | 1993 | ||
1944 | /* F10h, revD and later can do x8 ECC too */ | 1994 | /* F10h, revD and later can do x8 ECC too */ |
1945 | if ((c->x86 > 0x10 || c->x86_model > 7) && tmp & BIT(25)) | 1995 | if ((c->x86 > 0x10 || c->x86_model > 7) && tmp & BIT(25)) |
@@ -2356,6 +2406,11 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) | |||
2356 | pvt->ops = &amd64_family_types[F15_CPUS].ops; | 2406 | pvt->ops = &amd64_family_types[F15_CPUS].ops; |
2357 | break; | 2407 | break; |
2358 | 2408 | ||
2409 | case 0x16: | ||
2410 | fam_type = &amd64_family_types[F16_CPUS]; | ||
2411 | pvt->ops = &amd64_family_types[F16_CPUS].ops; | ||
2412 | break; | ||
2413 | |||
2359 | default: | 2414 | default: |
2360 | amd64_err("Unsupported family!\n"); | 2415 | amd64_err("Unsupported family!\n"); |
2361 | return NULL; | 2416 | return NULL; |
@@ -2581,6 +2636,14 @@ static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = { | |||
2581 | .class = 0, | 2636 | .class = 0, |
2582 | .class_mask = 0, | 2637 | .class_mask = 0, |
2583 | }, | 2638 | }, |
2639 | { | ||
2640 | .vendor = PCI_VENDOR_ID_AMD, | ||
2641 | .device = PCI_DEVICE_ID_AMD_16H_NB_F2, | ||
2642 | .subvendor = PCI_ANY_ID, | ||
2643 | .subdevice = PCI_ANY_ID, | ||
2644 | .class = 0, | ||
2645 | .class_mask = 0, | ||
2646 | }, | ||
2584 | 2647 | ||
2585 | {0, } | 2648 | {0, } |
2586 | }; | 2649 | }; |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 35637d83f235..2c6f113bae2b 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -172,7 +172,8 @@ | |||
172 | */ | 172 | */ |
173 | #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 | 173 | #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 |
174 | #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 | 174 | #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 |
175 | 175 | #define PCI_DEVICE_ID_AMD_16H_NB_F1 0x1531 | |
176 | #define PCI_DEVICE_ID_AMD_16H_NB_F2 0x1532 | ||
176 | 177 | ||
177 | /* | 178 | /* |
178 | * Function 1 - Address Map | 179 | * Function 1 - Address Map |
@@ -296,6 +297,7 @@ enum amd_families { | |||
296 | K8_CPUS = 0, | 297 | K8_CPUS = 0, |
297 | F10_CPUS, | 298 | F10_CPUS, |
298 | F15_CPUS, | 299 | F15_CPUS, |
300 | F16_CPUS, | ||
299 | NUM_FAMILIES, | 301 | NUM_FAMILIES, |
300 | }; | 302 | }; |
301 | 303 | ||