aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAristeu Rozanski <aris@redhat.com>2014-06-02 14:15:22 -0400
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-06-26 14:23:46 -0400
commit9e3754461507147ce5bffba5faaea7c182d64667 (patch)
treed681cc004f0dba3bb105702f5693e202a7778582
parenta497c3ba1d97fc69c1e78e7b96435ba8c2cb42ee (diff)
sb_edac: make memory type detection per memory controller
Haswell has different register, offset to determine memory type and supports DDR4 in some models. This patch makes it easier to have a different method depending on the memory controller type. Cc: Tony Luck <tony.luck@intel.com> Signed-off-by: Aristeu Rozanski <aris@redhat.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--drivers/edac/sb_edac.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index deea0dc9999b..44336cb0a561 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -279,8 +279,6 @@ static const u32 correrrthrsld[] = {
279 279
280#define IB_RANK_CFG_A 0x0320 280#define IB_RANK_CFG_A 0x0320
281 281
282#define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11)
283
284/* 282/*
285 * sbridge structs 283 * sbridge structs
286 */ 284 */
@@ -305,6 +303,7 @@ struct sbridge_info {
305 const struct interleave_pkg *interleave_pkg; 303 const struct interleave_pkg *interleave_pkg;
306 u8 max_sad; 304 u8 max_sad;
307 u8 max_interleave; 305 u8 max_interleave;
306 enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt);
308}; 307};
309 308
310struct sbridge_channel { 309struct sbridge_channel {
@@ -588,6 +587,25 @@ static u64 ibridge_get_tohm(struct sbridge_pvt *pvt)
588 return GET_TOHM(reg); 587 return GET_TOHM(reg);
589} 588}
590 589
590static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
591{
592 u32 reg;
593 enum mem_type mtype;
594
595 if (pvt->pci_ddrio) {
596 pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
597 &reg);
598 if (GET_BITFIELD(reg, 11, 11))
599 /* FIXME: Can also be LRDIMM */
600 mtype = MEM_RDDR3;
601 else
602 mtype = MEM_DDR3;
603 } else
604 mtype = MEM_UNKNOWN;
605
606 return mtype;
607}
608
591static inline u8 sad_pkg_socket(u8 pkg) 609static inline u8 sad_pkg_socket(u8 pkg)
592{ 610{
593 /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */ 611 /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */
@@ -698,21 +716,13 @@ static int get_dimm_config(struct mem_ctl_info *mci)
698 pvt->is_close_pg = false; 716 pvt->is_close_pg = false;
699 } 717 }
700 718
701 if (pvt->pci_ddrio) { 719 mtype = pvt->info.get_memory_type(pvt);
702 pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr, 720 if (mtype == MEM_RDDR3)
703 &reg); 721 edac_dbg(0, "Memory is registered\n");
704 if (IS_RDIMM_ENABLED(reg)) { 722 else if (mtype == MEM_UNKNOWN)
705 /* FIXME: Can also be LRDIMM */
706 edac_dbg(0, "Memory is registered\n");
707 mtype = MEM_RDDR3;
708 } else {
709 edac_dbg(0, "Memory is unregistered\n");
710 mtype = MEM_DDR3;
711 }
712 } else {
713 edac_dbg(0, "Cannot determine memory type\n"); 723 edac_dbg(0, "Cannot determine memory type\n");
714 mtype = MEM_UNKNOWN; 724 else
715 } 725 edac_dbg(0, "Memory is unregistered\n");
716 726
717 /* On all supported DDR3 DIMM types, there are 8 banks available */ 727 /* On all supported DDR3 DIMM types, there are 8 banks available */
718 banks = 8; 728 banks = 8;
@@ -1976,6 +1986,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
1976 pvt->info.get_tolm = ibridge_get_tolm; 1986 pvt->info.get_tolm = ibridge_get_tolm;
1977 pvt->info.get_tohm = ibridge_get_tohm; 1987 pvt->info.get_tohm = ibridge_get_tohm;
1978 pvt->info.dram_rule = ibridge_dram_rule; 1988 pvt->info.dram_rule = ibridge_dram_rule;
1989 pvt->info.get_memory_type = get_memory_type;
1979 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule); 1990 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
1980 pvt->info.interleave_list = ibridge_interleave_list; 1991 pvt->info.interleave_list = ibridge_interleave_list;
1981 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); 1992 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
@@ -1991,6 +2002,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
1991 pvt->info.get_tolm = sbridge_get_tolm; 2002 pvt->info.get_tolm = sbridge_get_tolm;
1992 pvt->info.get_tohm = sbridge_get_tohm; 2003 pvt->info.get_tohm = sbridge_get_tohm;
1993 pvt->info.dram_rule = sbridge_dram_rule; 2004 pvt->info.dram_rule = sbridge_dram_rule;
2005 pvt->info.get_memory_type = get_memory_type;
1994 pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule); 2006 pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
1995 pvt->info.interleave_list = sbridge_interleave_list; 2007 pvt->info.interleave_list = sbridge_interleave_list;
1996 pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); 2008 pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);