diff options
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/amd64_edac.c | 65 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 4 | ||||
-rw-r--r-- | drivers/edac/i7300_edac.c | 19 | ||||
-rw-r--r-- | drivers/edac/sb_edac.c | 53 |
4 files changed, 111 insertions, 30 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index e1d13c463c9..8b6a0343c22 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, * * F15h: we select which DCT we access using F1x10C[DctCfgSel] * + * F16h: has only 1 DCT */ static int k8_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, const char *func) @@ -340,6 +341,27 @@ static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct, base_bits = GENMASK(21, 31) | GENMASK(9, 15); mask_bits = GENMASK(21, 29) | GENMASK(9, 15); addr_shift = 4; + + /* + * F16h needs two addr_shift values: 8 for high and 6 for low + * (cf. F16h BKDG). + */ + } else if (boot_cpu_data.x86 == 0x16) { + csbase = pvt->csels[dct].csbases[csrow]; + csmask = pvt->csels[dct].csmasks[csrow >> 1]; + + *base = (csbase & GENMASK(5, 15)) << 6; + *base |= (csbase & GENMASK(19, 30)) << 8; + + *mask = ~0ULL; + /* poke holes for the csmask */ + *mask &= ~((GENMASK(5, 15) << 6) | + (GENMASK(19, 30) << 8)); + + *mask |= (csmask & GENMASK(5, 15)) << 6; + *mask |= (csmask & GENMASK(19, 30)) << 8; + + return; } else { csbase = pvt->csels[dct].csbases[csrow]; csmask = pvt->csels[dct].csmasks[csrow >> 1]; @@ -1150,6 +1172,21 @@ static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, return ddr3_cs_size(cs_mode, false); } +/* + * F16h has only limited cs_modes + */ +static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, + unsigned cs_mode) +{ + WARN_ON(cs_mode > 12); + + if (cs_mode == 6 || cs_mode == 8 || + cs_mode == 9 || cs_mode == 12) + return -1; + else + return ddr3_cs_size(cs_mode, false); +} + static void read_dram_ctl_register(struct amd64_pvt *pvt) { @@ -1587,6 +1624,17 @@ static struct amd64_family_type amd64_family_types[] = { .read_dct_pci_cfg = f15_read_dct_pci_cfg, } }, + [F16_CPUS] = { + .ctl_name = "F16h", + .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, + .f3_id = PCI_DEVICE_ID_AMD_16H_NB_F3, + .ops = { + .early_channel_count = f1x_early_channel_count, + .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, + .dbam_to_cs = f16_dbam_to_chip_select, + .read_dct_pci_cfg = f10_read_dct_pci_cfg, + } + }, }; /* @@ -1939,7 +1987,9 @@ static void read_mc_regs(struct amd64_pvt *pvt) if (c->x86 >= 0x10) { amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); - amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1); + if (c->x86 != 0x16) + /* F16h has only DCT0 */ + amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1); /* F10h, revD and later can do x8 ECC too */ 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) pvt->ops = &amd64_family_types[F15_CPUS].ops; break; + case 0x16: + fam_type = &amd64_family_types[F16_CPUS]; + pvt->ops = &amd64_family_types[F16_CPUS].ops; + break; + default: amd64_err("Unsupported family!\n"); return NULL; @@ -2581,6 +2636,14 @@ static DEFINE_PCI_DEVICE_TABLE(amd64_pci_table) = { .class = 0, .class_mask = 0, }, + { + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_16H_NB_F2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class = 0, + .class_mask = 0, + }, {0, } }; diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 35637d83f23..2c6f113bae2 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -172,7 +172,8 @@ */ #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 - +#define PCI_DEVICE_ID_AMD_16H_NB_F1 0x1531 +#define PCI_DEVICE_ID_AMD_16H_NB_F2 0x1532 /* * Function 1 - Address Map @@ -296,6 +297,7 @@ enum amd_families { K8_CPUS = 0, F10_CPUS, F15_CPUS, + F16_CPUS, NUM_FAMILIES, }; diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 087c27bc5d4..9004c64b169 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -750,15 +750,23 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) struct i7300_dimm_info *dinfo; int rc = -ENODEV; int mtr; - int ch, branch, slot, channel; + int ch, branch, slot, channel, max_channel, max_branch; struct dimm_info *dimm; pvt = mci->pvt_info; edac_dbg(2, "Memory Technology Registers:\n"); + if (IS_SINGLE_MODE(pvt->mc_settings_a)) { + max_branch = 1; + max_channel = 1; + } else { + max_branch = MAX_BRANCHES; + max_channel = MAX_CH_PER_BRANCH; + } + /* Get the AMB present registers for the four channels */ - for (branch = 0; branch < MAX_BRANCHES; branch++) { + for (branch = 0; branch < max_branch; branch++) { /* Read and dump branch 0's MTRs */ channel = to_channel(0, branch); pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], @@ -767,6 +775,9 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", channel, pvt->ambpresent[channel]); + if (max_channel == 1) + continue; + channel = to_channel(1, branch); pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_1, @@ -778,11 +789,11 @@ static int i7300_init_csrows(struct mem_ctl_info *mci) /* Get the set of MTR[0-7] regs by each branch */ for (slot = 0; slot < MAX_SLOTS; slot++) { int where = mtr_regs[slot]; - for (branch = 0; branch < MAX_BRANCHES; branch++) { + for (branch = 0; branch < max_branch; branch++) { pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], where, &pvt->mtr[slot][branch]); - for (ch = 0; ch < MAX_CH_PER_BRANCH; ch++) { + for (ch = 0; ch < max_channel; ch++) { int channel = to_channel(ch, branch); dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 57244f99561..e04462b6075 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -331,30 +331,31 @@ struct sbridge_pvt { u64 tolm, tohm; }; -#define PCI_DESCR(device, function, device_id) \ - .dev = (device), \ - .func = (function), \ - .dev_id = (device_id) +#define PCI_DESCR(device, function, device_id, opt) \ + .dev = (device), \ + .func = (function), \ + .dev_id = (device_id), \ + .optional = opt static const struct pci_id_descr pci_dev_descr_sbridge[] = { /* Processor Home Agent */ - { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0) }, + { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0) }, /* Memory controller */ - { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA) }, - { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS) }, - { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0) }, - { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1) }, - { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2) }, - { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3) }, - { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO) }, + { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0) }, + { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0) }, + { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0) }, + { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0) }, + { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0) }, + { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0) }, + { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1) }, /* System Address Decoder */ - { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0) }, - { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1) }, + { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0) }, + { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0) }, /* Broadcast Registers */ - { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR) }, + { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0) }, }; #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) } @@ -556,14 +557,19 @@ static int get_dimm_config(struct mem_ctl_info *mci) pvt->is_close_pg = false; } - pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, ®); - if (IS_RDIMM_ENABLED(reg)) { - /* FIXME: Can also be LRDIMM */ - edac_dbg(0, "Memory is registered\n"); - mtype = MEM_RDDR3; + if (pvt->pci_ddrio) { + pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, ®); + if (IS_RDIMM_ENABLED(reg)) { + /* FIXME: Can also be LRDIMM */ + edac_dbg(0, "Memory is registered\n"); + mtype = MEM_RDDR3; + } else { + edac_dbg(0, "Memory is unregistered\n"); + mtype = MEM_DDR3; + } } else { - edac_dbg(0, "Memory is unregistered\n"); - mtype = MEM_DDR3; + edac_dbg(0, "Cannot determine memory type\n"); + mtype = MEM_UNKNOWN; } /* On all supported DDR3 DIMM types, there are 8 banks available */ @@ -1303,8 +1309,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci, /* Check if everything were registered */ if (!pvt->pci_sad0 || !pvt->pci_sad1 || !pvt->pci_ha0 || - !pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta || - !pvt->pci_ddrio) + !pvt-> pci_tad || !pvt->pci_ras || !pvt->pci_ta) goto enodev; for (i = 0; i < NUM_CHANNELS; i++) { |