aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-06-22 21:48:29 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-10 10:44:45 -0400
commit0b2b7b7ec06ce615acd11374bf9a512e166dabb0 (patch)
treebd57e9162b2880aa52271d067ba36a409428c781 /drivers/edac
parent194a40feabb7cab38911a357c86e968e98024281 (diff)
i7core_edac: Add more status functions to EDAC driver
This patch were co-authored with Aristeu Rozanski. Signed-off-by: Aristeu Sergio <arozansk@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/i7core_edac.c114
1 files changed, 95 insertions, 19 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index b590f8468693..da40730bf9c9 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -62,6 +62,15 @@
62 62
63 /* OFFSETS for Devices 4,5 and 6 Function 0 */ 63 /* OFFSETS for Devices 4,5 and 6 Function 0 */
64 64
65#define MC_CHANNEL_DIMM_INIT_PARAMS 0x58
66 #define THREE_DIMMS_PRESENT (1 << 24)
67 #define SINGLE_QUAD_RANK_PRESENT (1 << 23)
68 #define QUAD_RANK_PRESENT (1 << 22)
69 #define REGISTERED_DIMM (1 << 15)
70
71#define MC_CHANNEL_RANK_PRESENT 0x7c
72 #define RANK_PRESENT_MASK 0xffff
73
65#define MC_CHANNEL_ADDR_MATCH 0xf0 74#define MC_CHANNEL_ADDR_MATCH 0xf0
66#define MC_CHANNEL_ERROR_MASK 0xf8 75#define MC_CHANNEL_ERROR_MASK 0xf8
67#define MC_CHANNEL_ERROR_INJECT 0xfc 76#define MC_CHANNEL_ERROR_INJECT 0xfc
@@ -74,6 +83,46 @@
74 #define NO_MASK_CACHELINE 0x00 83 #define NO_MASK_CACHELINE 0x00
75 #define REPEAT_EN 0x01 84 #define REPEAT_EN 0x01
76 85
86 /* OFFSETS for Devices 4,5 and 6 Function 1 */
87#define MC_DOD_CH_DIMM0 0x48
88#define MC_DOD_CH_DIMM1 0x4c
89#define MC_DOD_CH_DIMM2 0x50
90 #define RANKOFFSET_MASK ((1 << 12) | (1 << 11) | (1 << 10))
91 #define RANKOFFSET(x) ((x & RANKOFFSET_MASK) >> 10)
92 #define DIMM_PRESENT_MASK (1 << 9)
93 #define DIMM_PRESENT(x) (((x) & DIMM_PRESENT_MASK) >> 9)
94 #define NUMBANK_MASK ((1 << 8) | (1 << 7))
95 #define NUMBANK(x) (((x) & NUMBANK_MASK) >> 7)
96 #define NUMRANK_MASK ((1 << 6) | (1 << 5))
97 #define NUMRANK(x) (((x) & NUMRANK_MASK) >> 5)
98 #define NUMROW_MASK ((1 << 4) | (1 << 3))
99 #define NUMROW(x) (((x) & NUMROW_MASK) >> 3)
100 #define NUMCOL_MASK 3
101 #define NUMCOL(x) ((x) & NUMCOL_MASK)
102
103#define MC_SAG_CH_0 0x80
104#define MC_SAG_CH_1 0x84
105#define MC_SAG_CH_2 0x88
106#define MC_SAG_CH_3 0x8c
107#define MC_SAG_CH_4 0x90
108#define MC_SAG_CH_5 0x94
109#define MC_SAG_CH_6 0x98
110#define MC_SAG_CH_7 0x9c
111
112#define MC_RIR_LIMIT_CH_0 0x40
113#define MC_RIR_LIMIT_CH_1 0x44
114#define MC_RIR_LIMIT_CH_2 0x48
115#define MC_RIR_LIMIT_CH_3 0x4C
116#define MC_RIR_LIMIT_CH_4 0x50
117#define MC_RIR_LIMIT_CH_5 0x54
118#define MC_RIR_LIMIT_CH_6 0x58
119#define MC_RIR_LIMIT_CH_7 0x5C
120#define MC_RIR_LIMIT_MASK ((1 << 10) - 1)
121
122#define MC_RIR_WAY_CH 0x80
123 #define MC_RIR_WAY_OFFSET_MASK (((1 << 14) - 1) & ~0x7)
124 #define MC_RIR_WAY_RANK_MASK 0x7
125
77/* 126/*
78 * i7core structs 127 * i7core structs
79 */ 128 */
@@ -99,11 +148,17 @@ struct i7core_inject {
99 int channel, dimm, rank, bank, page, col; 148 int channel, dimm, rank, bank, page, col;
100}; 149};
101 150
151struct i7core_channel {
152 u32 ranks;
153 u32 dimms;
154};
155
102struct i7core_pvt { 156struct i7core_pvt {
103 struct pci_dev *pci_mcr; /* Dev 3:0 */ 157 struct pci_dev *pci_mcr; /* Dev 3:0 */
104 struct pci_dev *pci_ch[NUM_CHANS][NUM_FUNCS]; 158 struct pci_dev *pci_ch[NUM_CHANS][NUM_FUNCS];
105 struct i7core_info info; 159 struct i7core_info info;
106 struct i7core_inject inject; 160 struct i7core_inject inject;
161 struct i7core_channel channel[NUM_CHANS];
107}; 162};
108 163
109/* Device name and register DID (Device ID) */ 164/* Device name and register DID (Device ID) */
@@ -133,16 +188,12 @@ static struct edac_pci_ctl_info *i7core_pci;
133 ****************************************************************************/ 188 ****************************************************************************/
134 189
135 /* MC_CONTROL bits */ 190 /* MC_CONTROL bits */
136#define CH2_ACTIVE(pvt) ((pvt)->info.mc_control & 1 << 10) 191#define CH_ACTIVE(pvt, ch) ((pvt)->info.mc_control & 1 << (8 + ch))
137#define CH1_ACTIVE(pvt) ((pvt)->info.mc_control & 1 << 9)
138#define CH0_ACTIVE(pvt) ((pvt)->info.mc_control & 1 << 8)
139#define ECCx8(pvt) ((pvt)->info.mc_control & 1 << 1) 192#define ECCx8(pvt) ((pvt)->info.mc_control & 1 << 1)
140 193
141 /* MC_STATUS bits */ 194 /* MC_STATUS bits */
142#define ECC_ENABLED(pvt) ((pvt)->info.mc_status & 1 << 3) 195#define ECC_ENABLED(pvt) ((pvt)->info.mc_status & 1 << 3)
143#define CH2_DISABLED(pvt) ((pvt)->info.mc_status & 1 << 2) 196#define CH_DISABLED(pvt, ch) ((pvt)->info.mc_status & 1 << ch)
144#define CH1_DISABLED(pvt) ((pvt)->info.mc_status & 1 << 1)
145#define CH0_DISABLED(pvt) ((pvt)->info.mc_status & 1 << 0)
146 197
147 /* MC_MAX_DOD read functions */ 198 /* MC_MAX_DOD read functions */
148static inline int maxnumdimms(struct i7core_pvt *pvt) 199static inline int maxnumdimms(struct i7core_pvt *pvt)
@@ -189,19 +240,12 @@ static inline int maxnumcol(struct i7core_pvt *pvt)
189static int get_dimm_config(struct mem_ctl_info *mci) 240static int get_dimm_config(struct mem_ctl_info *mci)
190{ 241{
191 struct i7core_pvt *pvt = mci->pvt_info; 242 struct i7core_pvt *pvt = mci->pvt_info;
243 int i;
192 244
193 pci_read_config_dword(pvt->pci_mcr, MC_CONTROL, &pvt->info.mc_control); 245 pci_read_config_dword(pvt->pci_mcr, MC_CONTROL, &pvt->info.mc_control);
194 pci_read_config_dword(pvt->pci_mcr, MC_STATUS, &pvt->info.mc_status); 246 pci_read_config_dword(pvt->pci_mcr, MC_STATUS, &pvt->info.mc_status);
195 pci_read_config_dword(pvt->pci_mcr, MC_MAX_DOD, &pvt->info.max_dod); 247 pci_read_config_dword(pvt->pci_mcr, MC_MAX_DOD, &pvt->info.max_dod);
196 248
197 debugf0("Channels active [%c][%c][%c] - enabled [%c][%c][%c]\n",
198 CH0_ACTIVE(pvt)?'0':'-',
199 CH1_ACTIVE(pvt)?'1':'-',
200 CH2_ACTIVE(pvt)?'2':'-',
201 CH0_DISABLED(pvt)?'-':'0',
202 CH1_DISABLED(pvt)?'-':'1',
203 CH2_DISABLED(pvt)?'-':'2');
204
205 if (ECC_ENABLED(pvt)) 249 if (ECC_ENABLED(pvt))
206 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4); 250 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4);
207 else 251 else
@@ -213,6 +257,38 @@ static int get_dimm_config(struct mem_ctl_info *mci)
213 debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n", 257 debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n",
214 maxnumrow(pvt), maxnumcol(pvt)); 258 maxnumrow(pvt), maxnumcol(pvt));
215 259
260 debugf0("Memory channel configuration:\n");
261
262 for (i = 0; i < NUM_CHANS; i++) {
263 u32 data;
264
265 if (!CH_ACTIVE(pvt, i)) {
266 debugf0("Channel %i is not active\n", i);
267 continue;
268 }
269 if (CH_DISABLED(pvt, i)) {
270 debugf0("Channel %i is disabled\n", i);
271 continue;
272 }
273
274 pci_read_config_dword(pvt->pci_ch[i][0],
275 MC_CHANNEL_DIMM_INIT_PARAMS, &data);
276
277 pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2;
278
279 if (data & THREE_DIMMS_PRESENT)
280 pvt->channel[i].dimms = 3;
281 else if (data & SINGLE_QUAD_RANK_PRESENT)
282 pvt->channel[i].dimms = 1;
283 else
284 pvt->channel[i].dimms = 2;
285
286 debugf0("Channel %d (0x%08x): %d ranks, %d dimms "
287 "(%sregistered)\n", i, data,
288 pvt->channel[i].ranks, pvt->channel[i].dimms,
289 (data & REGISTERED_DIMM)? "" : "un" );
290 }
291
216 return 0; 292 return 0;
217} 293}
218 294
@@ -489,7 +565,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
489 if (pvt->inject.dimm < 0) 565 if (pvt->inject.dimm < 0)
490 mask |= 1l << 41; 566 mask |= 1l << 41;
491 else { 567 else {
492 if (maxnumdimms(pvt) > 2) 568 if (pvt->channel[pvt->inject.channel].dimms > 2)
493 mask |= (pvt->inject.dimm & 0x3l) << 35; 569 mask |= (pvt->inject.dimm & 0x3l) << 35;
494 else 570 else
495 mask |= (pvt->inject.dimm & 0x1l) << 36; 571 mask |= (pvt->inject.dimm & 0x1l) << 36;
@@ -499,7 +575,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
499 if (pvt->inject.rank < 0) 575 if (pvt->inject.rank < 0)
500 mask |= 1l << 40; 576 mask |= 1l << 40;
501 else { 577 else {
502 if (maxnumdimms(pvt) > 2) 578 if (pvt->channel[pvt->inject.channel].dimms > 2)
503 mask |= (pvt->inject.rank & 0x1l) << 34; 579 mask |= (pvt->inject.rank & 0x1l) << 34;
504 else 580 else
505 mask |= (pvt->inject.rank & 0x3l) << 34; 581 mask |= (pvt->inject.rank & 0x3l) << 34;
@@ -646,9 +722,6 @@ static int i7core_get_devices(struct mem_ctl_info *mci, int dev_idx)
646 } 722 }
647 pvt->pci_mcr=pdev; 723 pvt->pci_mcr=pdev;
648 724
649 /* Get dimm basic config */
650 get_dimm_config(mci);
651
652 /* Retrieve all needed functions at MTR channel controllers */ 725 /* Retrieve all needed functions at MTR channel controllers */
653 for (i = 0; i < NUM_CHANS; i++) { 726 for (i = 0; i < NUM_CHANS; i++) {
654 pdev = NULL; 727 pdev = NULL;
@@ -672,6 +745,9 @@ static int i7core_get_devices(struct mem_ctl_info *mci, int dev_idx)
672 } 745 }
673 i7core_printk(KERN_INFO, "Driver loaded.\n"); 746 i7core_printk(KERN_INFO, "Driver loaded.\n");
674 747
748 /* Get dimm basic config */
749 get_dimm_config(mci);
750
675 return 0; 751 return 0;
676} 752}
677 753