aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Wollesen <ericw@xmtp.net>2007-07-19 04:49:39 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:53 -0400
commiteb60705ac5a9869b2d078f0b472ea64b9b52b684 (patch)
treeb6d7300549568ad669b267cffc2bd1e91fad668a
parent63b7df9101895d1f0a259c567b3bab949a23075f (diff)
drivers/edac: new intel 5000 MC driver
Eric Wollesen ported the Bluesmoke Memory Controller driver (written by Doug Thompson) for the Intel 5000X/V/P (Blackford/Greencreek) chipset to the in kernel EDAC model. This patch incorporates the module for the 5000X/V/P chipset family [m.kozlowski@tuxland.pl: edac i5000 parenthesis balance fix] Signed-off-by: Eric Wollesen <ericw@xmtp.net> Signed-off-by: Doug Thompson <norsk5@xmission.com> Signed-off-by: Mariusz Kozlowski <m.kozlowski@tuxland.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/edac/Kconfig7
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/i5000_edac.c1477
3 files changed, 1485 insertions, 0 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index debf1d8e8b41..772a29079916 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -94,6 +94,13 @@ config EDAC_R82600
94 Support for error detection and correction on the Radisys 94 Support for error detection and correction on the Radisys
95 82600 embedded chipset. 95 82600 embedded chipset.
96 96
97config EDAC_I5000
98 tristate "Intel Greencreek/Blackford chipset"
99 depends on EDAC_MM_EDAC && X86 && PCI
100 help
101 Support for error detection and correction the Intel
102 Greekcreek/Blackford chipsets.
103
97choice 104choice
98 prompt "Error detecting method" 105 prompt "Error detecting method"
99 default EDAC_POLL 106 default EDAC_POLL
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 1c67cc809218..d2674fbde86f 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -15,6 +15,7 @@ edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
15edac_core-objs += edac_module.o edac_device_sysfs.o 15edac_core-objs += edac_module.o edac_device_sysfs.o
16 16
17obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o 17obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
18obj-$(CONFIG_EDAC_I5000) += i5000_edac.o
18obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o 19obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
19obj-$(CONFIG_EDAC_E752X) += e752x_edac.o 20obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
20obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o 21obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
new file mode 100644
index 000000000000..4d7e786065aa
--- /dev/null
+++ b/drivers/edac/i5000_edac.c
@@ -0,0 +1,1477 @@
1/*
2 * Intel 5000(P/V/X) class Memory Controllers kernel module
3 *
4 * This file may be distributed under the terms of the
5 * GNU General Public License.
6 *
7 * Written by Douglas Thompson Linux Networx (http://lnxi.com)
8 * norsk5@xmission.com
9 *
10 * This module is based on the following document:
11 *
12 * Intel 5000X Chipset Memory Controller Hub (MCH) - Datasheet
13 * http://developer.intel.com/design/chipsets/datashts/313070.htm
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/pci.h>
20#include <linux/pci_ids.h>
21#include <linux/slab.h>
22#include <asm/mmzone.h>
23
24#include "edac_mc.h"
25
26/*
27 * Alter this version for the I5000 module when modifications are made
28 */
29#define I5000_REVISION " Ver: 2.0.11.devel " __DATE__
30
31#define i5000_printk(level, fmt, arg...) \
32 edac_printk(level, "i5000", fmt, ##arg)
33
34#define i5000_mc_printk(mci, level, fmt, arg...) \
35 edac_mc_chipset_printk(mci, level, "i5000", fmt, ##arg)
36
37#ifndef PCI_DEVICE_ID_INTEL_FBD_0
38#define PCI_DEVICE_ID_INTEL_FBD_0 0x25F5
39#endif
40#ifndef PCI_DEVICE_ID_INTEL_FBD_1
41#define PCI_DEVICE_ID_INTEL_FBD_1 0x25F6
42#endif
43
44/* Device 16,
45 * Function 0: System Address
46 * Function 1: Memory Branch Map, Control, Errors Register
47 * Function 2: FSB Error Registers
48 *
49 * All 3 functions of Device 16 (0,1,2) share the SAME DID
50 */
51#define PCI_DEVICE_ID_INTEL_I5000_DEV16 0x25F0
52
53/* OFFSETS for Function 0 */
54
55/* OFFSETS for Function 1 */
56#define AMBASE 0x48
57#define MAXCH 0x56
58#define MAXDIMMPERCH 0x57
59#define TOLM 0x6C
60#define REDMEMB 0x7C
61#define RED_ECC_LOCATOR(x) ((x) & 0x3FFFF)
62#define REC_ECC_LOCATOR_EVEN(x) ((x) & 0x001FF)
63#define REC_ECC_LOCATOR_ODD(x) ((x) & 0x3FE00)
64#define MIR0 0x80
65#define MIR1 0x84
66#define MIR2 0x88
67#define AMIR0 0x8C
68#define AMIR1 0x90
69#define AMIR2 0x94
70
71#define FERR_FAT_FBD 0x98
72#define NERR_FAT_FBD 0x9C
73#define EXTRACT_FBDCHAN_INDX(x) (((x)>>28) & 0x3)
74#define FERR_FAT_FBDCHAN 0x30000000
75#define FERR_FAT_M3ERR 0x00000004
76#define FERR_FAT_M2ERR 0x00000002
77#define FERR_FAT_M1ERR 0x00000001
78#define FERR_FAT_MASK (FERR_FAT_M1ERR | \
79 FERR_FAT_M2ERR | \
80 FERR_FAT_M3ERR)
81
82#define FERR_NF_FBD 0xA0
83
84/* Thermal and SPD or BFD errors */
85#define FERR_NF_M28ERR 0x01000000
86#define FERR_NF_M27ERR 0x00800000
87#define FERR_NF_M26ERR 0x00400000
88#define FERR_NF_M25ERR 0x00200000
89#define FERR_NF_M24ERR 0x00100000
90#define FERR_NF_M23ERR 0x00080000
91#define FERR_NF_M22ERR 0x00040000
92#define FERR_NF_M21ERR 0x00020000
93
94/* Correctable errors */
95#define FERR_NF_M20ERR 0x00010000
96#define FERR_NF_M19ERR 0x00008000
97#define FERR_NF_M18ERR 0x00004000
98#define FERR_NF_M17ERR 0x00002000
99
100/* Non-Retry or redundant Retry errors */
101#define FERR_NF_M16ERR 0x00001000
102#define FERR_NF_M15ERR 0x00000800
103#define FERR_NF_M14ERR 0x00000400
104#define FERR_NF_M13ERR 0x00000200
105
106/* Uncorrectable errors */
107#define FERR_NF_M12ERR 0x00000100
108#define FERR_NF_M11ERR 0x00000080
109#define FERR_NF_M10ERR 0x00000040
110#define FERR_NF_M9ERR 0x00000020
111#define FERR_NF_M8ERR 0x00000010
112#define FERR_NF_M7ERR 0x00000008
113#define FERR_NF_M6ERR 0x00000004
114#define FERR_NF_M5ERR 0x00000002
115#define FERR_NF_M4ERR 0x00000001
116
117#define FERR_NF_UNCORRECTABLE (FERR_NF_M12ERR | \
118 FERR_NF_M11ERR | \
119 FERR_NF_M10ERR | \
120 FERR_NF_M8ERR | \
121 FERR_NF_M7ERR | \
122 FERR_NF_M6ERR | \
123 FERR_NF_M5ERR | \
124 FERR_NF_M4ERR)
125#define FERR_NF_CORRECTABLE (FERR_NF_M20ERR | \
126 FERR_NF_M19ERR | \
127 FERR_NF_M18ERR | \
128 FERR_NF_M17ERR)
129#define FERR_NF_DIMM_SPARE (FERR_NF_M27ERR | \
130 FERR_NF_M28ERR)
131#define FERR_NF_THERMAL (FERR_NF_M26ERR | \
132 FERR_NF_M25ERR | \
133 FERR_NF_M24ERR | \
134 FERR_NF_M23ERR)
135#define FERR_NF_SPD_PROTOCOL (FERR_NF_M22ERR)
136#define FERR_NF_NORTH_CRC (FERR_NF_M21ERR)
137#define FERR_NF_NON_RETRY (FERR_NF_M13ERR | \
138 FERR_NF_M14ERR | \
139 FERR_NF_M15ERR)
140
141#define NERR_NF_FBD 0xA4
142#define FERR_NF_MASK (FERR_NF_UNCORRECTABLE | \
143 FERR_NF_CORRECTABLE | \
144 FERR_NF_DIMM_SPARE | \
145 FERR_NF_THERMAL | \
146 FERR_NF_SPD_PROTOCOL | \
147 FERR_NF_NORTH_CRC | \
148 FERR_NF_NON_RETRY)
149
150#define EMASK_FBD 0xA8
151#define EMASK_FBD_M28ERR 0x08000000
152#define EMASK_FBD_M27ERR 0x04000000
153#define EMASK_FBD_M26ERR 0x02000000
154#define EMASK_FBD_M25ERR 0x01000000
155#define EMASK_FBD_M24ERR 0x00800000
156#define EMASK_FBD_M23ERR 0x00400000
157#define EMASK_FBD_M22ERR 0x00200000
158#define EMASK_FBD_M21ERR 0x00100000
159#define EMASK_FBD_M20ERR 0x00080000
160#define EMASK_FBD_M19ERR 0x00040000
161#define EMASK_FBD_M18ERR 0x00020000
162#define EMASK_FBD_M17ERR 0x00010000
163
164#define EMASK_FBD_M15ERR 0x00004000
165#define EMASK_FBD_M14ERR 0x00002000
166#define EMASK_FBD_M13ERR 0x00001000
167#define EMASK_FBD_M12ERR 0x00000800
168#define EMASK_FBD_M11ERR 0x00000400
169#define EMASK_FBD_M10ERR 0x00000200
170#define EMASK_FBD_M9ERR 0x00000100
171#define EMASK_FBD_M8ERR 0x00000080
172#define EMASK_FBD_M7ERR 0x00000040
173#define EMASK_FBD_M6ERR 0x00000020
174#define EMASK_FBD_M5ERR 0x00000010
175#define EMASK_FBD_M4ERR 0x00000008
176#define EMASK_FBD_M3ERR 0x00000004
177#define EMASK_FBD_M2ERR 0x00000002
178#define EMASK_FBD_M1ERR 0x00000001
179
180#define ENABLE_EMASK_FBD_FATAL_ERRORS (EMASK_FBD_M1ERR | \
181 EMASK_FBD_M2ERR | \
182 EMASK_FBD_M3ERR)
183
184#define ENABLE_EMASK_FBD_UNCORRECTABLE (EMASK_FBD_M4ERR | \
185 EMASK_FBD_M5ERR | \
186 EMASK_FBD_M6ERR | \
187 EMASK_FBD_M7ERR | \
188 EMASK_FBD_M8ERR | \
189 EMASK_FBD_M9ERR | \
190 EMASK_FBD_M10ERR | \
191 EMASK_FBD_M11ERR | \
192 EMASK_FBD_M12ERR)
193#define ENABLE_EMASK_FBD_CORRECTABLE (EMASK_FBD_M17ERR | \
194 EMASK_FBD_M18ERR | \
195 EMASK_FBD_M19ERR | \
196 EMASK_FBD_M20ERR)
197#define ENABLE_EMASK_FBD_DIMM_SPARE (EMASK_FBD_M27ERR | \
198 EMASK_FBD_M28ERR)
199#define ENABLE_EMASK_FBD_THERMALS (EMASK_FBD_M26ERR | \
200 EMASK_FBD_M25ERR | \
201 EMASK_FBD_M24ERR | \
202 EMASK_FBD_M23ERR)
203#define ENABLE_EMASK_FBD_SPD_PROTOCOL (EMASK_FBD_M22ERR)
204#define ENABLE_EMASK_FBD_NORTH_CRC (EMASK_FBD_M21ERR)
205#define ENABLE_EMASK_FBD_NON_RETRY (EMASK_FBD_M15ERR | \
206 EMASK_FBD_M14ERR | \
207 EMASK_FBD_M13ERR)
208
209#define ENABLE_EMASK_ALL (ENABLE_EMASK_FBD_NON_RETRY | \
210 ENABLE_EMASK_FBD_NORTH_CRC | \
211 ENABLE_EMASK_FBD_SPD_PROTOCOL | \
212 ENABLE_EMASK_FBD_THERMALS | \
213 ENABLE_EMASK_FBD_DIMM_SPARE | \
214 ENABLE_EMASK_FBD_FATAL_ERRORS | \
215 ENABLE_EMASK_FBD_CORRECTABLE | \
216 ENABLE_EMASK_FBD_UNCORRECTABLE)
217
218#define ERR0_FBD 0xAC
219#define ERR1_FBD 0xB0
220#define ERR2_FBD 0xB4
221#define MCERR_FBD 0xB8
222#define NRECMEMA 0xBE
223#define NREC_BANK(x) (((x)>>12) & 0x7)
224#define NREC_RDWR(x) (((x)>>11) & 1)
225#define NREC_RANK(x) (((x)>>8) & 0x7)
226#define NRECMEMB 0xC0
227#define NREC_CAS(x) (((x)>>16) & 0xFFFFFF)
228#define NREC_RAS(x) ((x) & 0x7FFF)
229#define NRECFGLOG 0xC4
230#define NREEECFBDA 0xC8
231#define NREEECFBDB 0xCC
232#define NREEECFBDC 0xD0
233#define NREEECFBDD 0xD4
234#define NREEECFBDE 0xD8
235#define REDMEMA 0xDC
236#define RECMEMA 0xE2
237#define REC_BANK(x) (((x)>>12) & 0x7)
238#define REC_RDWR(x) (((x)>>11) & 1)
239#define REC_RANK(x) (((x)>>8) & 0x7)
240#define RECMEMB 0xE4
241#define REC_CAS(x) (((x)>>16) & 0xFFFFFF)
242#define REC_RAS(x) ((x) & 0x7FFF)
243#define RECFGLOG 0xE8
244#define RECFBDA 0xEC
245#define RECFBDB 0xF0
246#define RECFBDC 0xF4
247#define RECFBDD 0xF8
248#define RECFBDE 0xFC
249
250/* OFFSETS for Function 2 */
251
252/*
253 * Device 21,
254 * Function 0: Memory Map Branch 0
255 *
256 * Device 22,
257 * Function 0: Memory Map Branch 1
258 */
259#define PCI_DEVICE_ID_I5000_BRANCH_0 0x25F5
260#define PCI_DEVICE_ID_I5000_BRANCH_1 0x25F6
261
262#define AMB_PRESENT_0 0x64
263#define AMB_PRESENT_1 0x66
264#define MTR0 0x80
265#define MTR1 0x84
266#define MTR2 0x88
267#define MTR3 0x8C
268
269#define NUM_MTRS 4
270#define CHANNELS_PER_BRANCH (2)
271
272/* Defines to extract the vaious fields from the
273 * MTRx - Memory Technology Registers
274 */
275#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (0x1 << 8))
276#define MTR_DRAM_WIDTH(mtr) ((((mtr) >> 6) & 0x1) ? 8 : 4)
277#define MTR_DRAM_BANKS(mtr) ((((mtr) >> 5) & 0x1) ? 8 : 4)
278#define MTR_DRAM_BANKS_ADDR_BITS(mtr) ((MTR_DRAM_BANKS(mtr) == 8) ? 3 : 2)
279#define MTR_DIMM_RANK(mtr) (((mtr) >> 4) & 0x1)
280#define MTR_DIMM_RANK_ADDR_BITS(mtr) (MTR_DIM_RANKS(mtr) ? 2 : 1)
281#define MTR_DIMM_ROWS(mtr) (((mtr) >> 2) & 0x3)
282#define MTR_DIMM_ROWS_ADDR_BITS(mtr) (MTR_DIMM_ROWS(mtr) + 13)
283#define MTR_DIMM_COLS(mtr) ((mtr) & 0x3)
284#define MTR_DIMM_COLS_ADDR_BITS(mtr) (MTR_DIMM_COLS(mtr) + 10)
285
286#ifdef CONFIG_EDAC_DEBUG
287static char *numrow_toString[] = {
288 "8,192 - 13 rows",
289 "16,384 - 14 rows",
290 "32,768 - 15 rows",
291 "reserved"
292};
293
294static char *numcol_toString[] = {
295 "1,024 - 10 columns",
296 "2,048 - 11 columns",
297 "4,096 - 12 columns",
298 "reserved"
299};
300#endif
301
302/* Enumeration of supported devices */
303enum i5000_chips {
304 I5000P = 0,
305 I5000V = 1, /* future */
306 I5000X = 2 /* future */
307};
308
309/* Device name and register DID (Device ID) */
310struct i5000_dev_info {
311 const char *ctl_name; /* name for this device */
312 u16 fsb_mapping_errors; /* DID for the branchmap,control */
313};
314
315/* Table of devices attributes supported by this driver */
316static const struct i5000_dev_info i5000_devs[] = {
317 [I5000P] = {
318 .ctl_name = "I5000",
319 .fsb_mapping_errors = PCI_DEVICE_ID_INTEL_I5000_DEV16,
320 },
321};
322
323struct i5000_dimm_info {
324 int megabytes; /* size, 0 means not present */
325 int dual_rank;
326};
327
328#define MAX_CHANNELS 6 /* max possible channels */
329#define MAX_CSROWS (8*2) /* max possible csrows per channel */
330
331/* driver private data structure */
332struct i5000_pvt {
333 struct pci_dev *system_address; /* 16.0 */
334 struct pci_dev *branchmap_werrors; /* 16.1 */
335 struct pci_dev *fsb_error_regs; /* 16.2 */
336 struct pci_dev *branch_0; /* 21.0 */
337 struct pci_dev *branch_1; /* 22.0 */
338
339 int node_id; /* ID of this node */
340
341 u16 tolm; /* top of low memory */
342 u64 ambase; /* AMB BAR */
343
344 u16 mir0, mir1, mir2;
345
346 u16 b0_mtr[NUM_MTRS]; /* Memory Technlogy Reg */
347 u16 b0_ambpresent0; /* Branch 0, Channel 0 */
348 u16 b0_ambpresent1; /* Brnach 0, Channel 1 */
349
350 u16 b1_mtr[NUM_MTRS]; /* Memory Technlogy Reg */
351 u16 b1_ambpresent0; /* Branch 1, Channel 8 */
352 u16 b1_ambpresent1; /* Branch 1, Channel 1 */
353
354 /* DIMM infomation matrix, allocating architecture maximums */
355 struct i5000_dimm_info dimm_info[MAX_CSROWS][MAX_CHANNELS];
356
357 /* Actual values for this controller */
358 int maxch; /* Max channels */
359 int maxdimmperch; /* Max DIMMs per channel */
360};
361
362/* I5000 MCH error information retrieved from Hardware */
363struct i5000_error_info {
364
365 /* These registers are always read from the MC */
366 u32 ferr_fat_fbd; /* First Errors Fatal */
367 u32 nerr_fat_fbd; /* Next Errors Fatal */
368 u32 ferr_nf_fbd; /* First Errors Non-Fatal */
369 u32 nerr_nf_fbd; /* Next Errors Non-Fatal */
370
371 /* These registers are input ONLY if there was a Recoverable Error */
372 u32 redmemb; /* Recoverable Mem Data Error log B */
373 u16 recmema; /* Recoverable Mem Error log A */
374 u32 recmemb; /* Recoverable Mem Error log B */
375
376 /* These registers are input ONLY if there was a
377 * Non-Recoverable Error */
378 u16 nrecmema; /* Non-Recoverable Mem log A */
379 u16 nrecmemb; /* Non-Recoverable Mem log B */
380
381};
382
383/******************************************************************************
384 * i5000_get_error_info Retrieve the hardware error information from
385 * the hardware and cache it in the 'info'
386 * structure
387 */
388static void i5000_get_error_info(struct mem_ctl_info *mci,
389 struct i5000_error_info * info)
390{
391 struct i5000_pvt *pvt;
392 u32 value;
393
394 pvt = (struct i5000_pvt *)mci->pvt_info;
395
396 /* read in the 1st FATAL error register */
397 pci_read_config_dword(pvt->branchmap_werrors, FERR_FAT_FBD, &value);
398
399 /* Mask only the bits that the doc says are valid
400 */
401 value &= (FERR_FAT_FBDCHAN | FERR_FAT_MASK);
402
403 /* If there is an error, then read in the */
404 /* NEXT FATAL error register and the Memory Error Log Register A */
405 if (value & FERR_FAT_MASK) {
406 info->ferr_fat_fbd = value;
407
408 /* harvest the various error data we need */
409 pci_read_config_dword(pvt->branchmap_werrors,
410 NERR_FAT_FBD, &info->nerr_fat_fbd);
411 pci_read_config_word(pvt->branchmap_werrors,
412 NRECMEMA, &info->nrecmema);
413 pci_read_config_word(pvt->branchmap_werrors,
414 NRECMEMB, &info->nrecmemb);
415
416 /* Clear the error bits, by writing them back */
417 pci_write_config_dword(pvt->branchmap_werrors,
418 FERR_FAT_FBD, value);
419 } else {
420 info->ferr_fat_fbd = 0;
421 info->nerr_fat_fbd = 0;
422 info->nrecmema = 0;
423 info->nrecmemb = 0;
424 }
425
426 /* read in the 1st NON-FATAL error register */
427 pci_read_config_dword(pvt->branchmap_werrors, FERR_NF_FBD, &value);
428
429 /* If there is an error, then read in the 1st NON-FATAL error
430 * register as well */
431 if (value & FERR_NF_MASK) {
432 info->ferr_nf_fbd = value;
433
434 /* harvest the various error data we need */
435 pci_read_config_dword(pvt->branchmap_werrors,
436 NERR_NF_FBD, &info->nerr_nf_fbd);
437 pci_read_config_word(pvt->branchmap_werrors,
438 RECMEMA, &info->recmema);
439 pci_read_config_dword(pvt->branchmap_werrors,
440 RECMEMB, &info->recmemb);
441 pci_read_config_dword(pvt->branchmap_werrors,
442 REDMEMB, &info->redmemb);
443
444 /* Clear the error bits, by writing them back */
445 pci_write_config_dword(pvt->branchmap_werrors,
446 FERR_NF_FBD, value);
447 } else {
448 info->ferr_nf_fbd = 0;
449 info->nerr_nf_fbd = 0;
450 info->recmema = 0;
451 info->recmemb = 0;
452 info->redmemb = 0;
453 }
454}
455
456/******************************************************************************
457 * i5000_process_fatal_error_info(struct mem_ctl_info *mci,
458 * struct i5000_error_info *info,
459 * int handle_errors);
460 *
461 * handle the Intel FATAL errors, if any
462 */
463static void i5000_process_fatal_error_info(struct mem_ctl_info *mci,
464 struct i5000_error_info * info,
465 int handle_errors)
466{
467 char msg[EDAC_MC_LABEL_LEN + 1 + 90];
468 u32 allErrors;
469 int branch;
470 int channel;
471 int bank;
472 int rank;
473 int rdwr;
474 int ras, cas;
475
476 /* mask off the Error bits that are possible */
477 allErrors = (info->ferr_fat_fbd & FERR_FAT_MASK);
478 if (!allErrors)
479 return; /* if no error, return now */
480
481 /* ONLY ONE of the possible error bits will be set, as per the docs */
482 i5000_mc_printk(mci, KERN_ERR,
483 "FATAL ERRORS Found!!! 1st FATAL Err Reg= 0x%x\n",
484 allErrors);
485
486 branch = EXTRACT_FBDCHAN_INDX(info->ferr_fat_fbd);
487 channel = branch;
488
489 /* Use the NON-Recoverable macros to extract data */
490 bank = NREC_BANK(info->nrecmema);
491 rank = NREC_RANK(info->nrecmema);
492 rdwr = NREC_RDWR(info->nrecmema);
493 ras = NREC_RAS(info->nrecmemb);
494 cas = NREC_CAS(info->nrecmemb);
495
496 debugf0("\t\tCSROW= %d Channels= %d,%d (Branch= %d "
497 "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
498 rank, channel, channel + 1, branch >> 1, bank,
499 rdwr ? "Write" : "Read", ras, cas);
500
501 /* Only 1 bit will be on */
502 if (allErrors & FERR_FAT_M1ERR) {
503 i5000_mc_printk(mci, KERN_ERR,
504 "Alert on non-redundant retry or fast "
505 "reset timeout\n");
506
507 } else if (allErrors & FERR_FAT_M2ERR) {
508 i5000_mc_printk(mci, KERN_ERR,
509 "Northbound CRC error on non-redundant "
510 "retry\n");
511
512 } else if (allErrors & FERR_FAT_M3ERR) {
513 i5000_mc_printk(mci, KERN_ERR,
514 ">Tmid Thermal event with intelligent "
515 "throttling disabled\n");
516 }
517
518 /* Form out message */
519 snprintf(msg, sizeof(msg),
520 "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d CAS=%d "
521 "FATAL Err=0x%x)",
522 branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
523 allErrors);
524
525 /* Call the helper to output message */
526 edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
527}
528
529/******************************************************************************
530 * i5000_process_fatal_error_info(struct mem_ctl_info *mci,
531 * struct i5000_error_info *info,
532 * int handle_errors);
533 *
534 * handle the Intel NON-FATAL errors, if any
535 */
536static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci,
537 struct i5000_error_info * info,
538 int handle_errors)
539{
540 char msg[EDAC_MC_LABEL_LEN + 1 + 90];
541 u32 allErrors;
542 u32 ue_errors;
543 u32 ce_errors;
544 u32 misc_errors;
545 int branch;
546 int channel;
547 int bank;
548 int rank;
549 int rdwr;
550 int ras, cas;
551
552 /* mask off the Error bits that are possible */
553 allErrors = (info->ferr_nf_fbd & FERR_NF_MASK);
554 if (!allErrors)
555 return; /* if no error, return now */
556
557 /* ONLY ONE of the possible error bits will be set, as per the docs */
558 i5000_mc_printk(mci, KERN_WARNING,
559 "NON-FATAL ERRORS Found!!! 1st NON-FATAL Err "
560 "Reg= 0x%x\n", allErrors);
561
562 ue_errors = allErrors & FERR_NF_UNCORRECTABLE;
563 if (ue_errors) {
564 debugf0("\tUncorrected bits= 0x%x\n", ue_errors);
565
566 branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
567 channel = branch;
568 bank = NREC_BANK(info->nrecmema);
569 rank = NREC_RANK(info->nrecmema);
570 rdwr = NREC_RDWR(info->nrecmema);
571 ras = NREC_RAS(info->nrecmemb);
572 cas = NREC_CAS(info->nrecmemb);
573
574 debugf0
575 ("\t\tCSROW= %d Channels= %d,%d (Branch= %d "
576 "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
577 rank, channel, channel + 1, branch >> 1, bank,
578 rdwr ? "Write" : "Read", ras, cas);
579
580 /* Form out message */
581 snprintf(msg, sizeof(msg),
582 "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
583 "CAS=%d, UE Err=0x%x)",
584 branch >> 1, bank, rdwr ? "Write" : "Read", ras, cas,
585 ue_errors);
586
587 /* Call the helper to output message */
588 edac_mc_handle_fbd_ue(mci, rank, channel, channel + 1, msg);
589 }
590
591 /* Check correctable errors */
592 ce_errors = allErrors & FERR_NF_CORRECTABLE;
593 if (ce_errors) {
594 debugf0("\tCorrected bits= 0x%x\n", ce_errors);
595
596 branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd);
597
598 channel = 0;
599 if (REC_ECC_LOCATOR_ODD(info->redmemb))
600 channel = 1;
601
602 /* Convert channel to be based from zero, instead of
603 * from branch base of 0 */
604 channel += branch;
605
606 bank = REC_BANK(info->recmema);
607 rank = REC_RANK(info->recmema);
608 rdwr = REC_RDWR(info->recmema);
609 ras = REC_RAS(info->recmemb);
610 cas = REC_CAS(info->recmemb);
611
612 debugf0("\t\tCSROW= %d Channel= %d (Branch %d "
613 "DRAM Bank= %d rdwr= %s ras= %d cas= %d)\n",
614 rank, channel, branch >> 1, bank,
615 rdwr ? "Write" : "Read", ras, cas);
616
617 /* Form out message */
618 snprintf(msg, sizeof(msg),
619 "(Branch=%d DRAM-Bank=%d RDWR=%s RAS=%d "
620 "CAS=%d, CE Err=0x%x)", branch >> 1, bank,
621 rdwr ? "Write" : "Read", ras, cas, ce_errors);
622
623 /* Call the helper to output message */
624 edac_mc_handle_fbd_ce(mci, rank, channel, msg);
625 }
626
627 /* See if any of the thermal errors have fired */
628 misc_errors = allErrors & FERR_NF_THERMAL;
629 if (misc_errors) {
630 i5000_printk(KERN_WARNING, "\tTHERMAL Error, bits= 0x%x\n",
631 misc_errors);
632 }
633
634 /* See if any of the thermal errors have fired */
635 misc_errors = allErrors & FERR_NF_NON_RETRY;
636 if (misc_errors) {
637 i5000_printk(KERN_WARNING, "\tNON-Retry Errors, bits= 0x%x\n",
638 misc_errors);
639 }
640
641 /* See if any of the thermal errors have fired */
642 misc_errors = allErrors & FERR_NF_NORTH_CRC;
643 if (misc_errors) {
644 i5000_printk(KERN_WARNING,
645 "\tNORTHBOUND CRC Error, bits= 0x%x\n",
646 misc_errors);
647 }
648
649 /* See if any of the thermal errors have fired */
650 misc_errors = allErrors & FERR_NF_SPD_PROTOCOL;
651 if (misc_errors) {
652 i5000_printk(KERN_WARNING,
653 "\tSPD Protocol Error, bits= 0x%x\n",
654 misc_errors);
655 }
656
657 /* See if any of the thermal errors have fired */
658 misc_errors = allErrors & FERR_NF_DIMM_SPARE;
659 if (misc_errors) {
660 i5000_printk(KERN_WARNING, "\tDIMM-Spare Error, bits= 0x%x\n",
661 misc_errors);
662 }
663}
664
665/******************************************************************************
666 * i5000_process_error_info Process the error info that is
667 * in the 'info' structure, previously retrieved from hardware
668 */
669static void i5000_process_error_info(struct mem_ctl_info *mci,
670 struct i5000_error_info * info,
671 int handle_errors)
672{
673 /* First handle any fatal errors that occurred */
674 i5000_process_fatal_error_info(mci, info, handle_errors);
675
676 /* now handle any non-fatal errors that occurred */
677 i5000_process_nonfatal_error_info(mci, info, handle_errors);
678}
679
680/******************************************************************************
681 * i5000_clear_error Retrieve any error from the hardware
682 * but do NOT process that error.
683 * Used for 'clearing' out of previous errors
684 * Called by the Core module.
685 */
686static void i5000_clear_error(struct mem_ctl_info *mci)
687{
688 struct i5000_error_info info;
689
690 i5000_get_error_info(mci, &info);
691}
692
693/******************************************************************************
694 * i5000_check_error Retrieve and process errors reported by the
695 * hardware. Called by the Core module.
696 */
697static void i5000_check_error(struct mem_ctl_info *mci)
698{
699 struct i5000_error_info info;
700 debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__);
701 i5000_get_error_info(mci, &info);
702 i5000_process_error_info(mci, &info, 1);
703}
704
705/******************************************************************************
706 * i5000_get_devices Find and perform 'get' operation on the MCH's
707 * device/functions we want to reference for this driver
708 *
709 * Need to 'get' device 16 func 1 and func 2
710 */
711static int i5000_get_devices(struct mem_ctl_info *mci, int dev_idx)
712{
713 //const struct i5000_dev_info *i5000_dev = &i5000_devs[dev_idx];
714 struct i5000_pvt *pvt;
715 struct pci_dev *pdev;
716
717 pvt = (struct i5000_pvt *)mci->pvt_info;
718
719 /* Attempt to 'get' the MCH register we want */
720 pdev = NULL;
721 while (1) {
722 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
723 PCI_DEVICE_ID_INTEL_I5000_DEV16, pdev);
724
725 /* End of list, leave */
726 if (pdev == NULL) {
727 i5000_printk(KERN_ERR,
728 "'system address,Process Bus' "
729 "device not found:"
730 "vendor 0x%x device 0x%x FUNC 1 "
731 "(broken BIOS?)\n",
732 PCI_VENDOR_ID_INTEL,
733 PCI_DEVICE_ID_INTEL_I5000_DEV16);
734
735 return 1;
736 }
737
738 /* Scan for device 16 func 1 */
739 if (PCI_FUNC(pdev->devfn) == 1)
740 break;
741 }
742
743 pvt->branchmap_werrors = pdev;
744
745 /* Attempt to 'get' the MCH register we want */
746 pdev = NULL;
747 while (1) {
748 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
749 PCI_DEVICE_ID_INTEL_I5000_DEV16, pdev);
750
751 if (pdev == NULL) {
752 i5000_printk(KERN_ERR,
753 "MC: 'branchmap,control,errors' "
754 "device not found:"
755 "vendor 0x%x device 0x%x Func 2 "
756 "(broken BIOS?)\n",
757 PCI_VENDOR_ID_INTEL,
758 PCI_DEVICE_ID_INTEL_I5000_DEV16);
759
760 pci_dev_put(pvt->branchmap_werrors);
761 return 1;
762 }
763
764 /* Scan for device 16 func 1 */
765 if (PCI_FUNC(pdev->devfn) == 2)
766 break;
767 }
768
769 pvt->fsb_error_regs = pdev;
770
771 debugf1("System Address, processor bus- PCI Bus ID: %s %x:%x\n",
772 pci_name(pvt->system_address),
773 pvt->system_address->vendor, pvt->system_address->device);
774 debugf1("Branchmap, control and errors - PCI Bus ID: %s %x:%x\n",
775 pci_name(pvt->branchmap_werrors),
776 pvt->branchmap_werrors->vendor, pvt->branchmap_werrors->device);
777 debugf1("FSB Error Regs - PCI Bus ID: %s %x:%x\n",
778 pci_name(pvt->fsb_error_regs),
779 pvt->fsb_error_regs->vendor, pvt->fsb_error_regs->device);
780
781 pdev = NULL;
782 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
783 PCI_DEVICE_ID_I5000_BRANCH_0, pdev);
784
785 if (pdev == NULL) {
786 i5000_printk(KERN_ERR,
787 "MC: 'BRANCH 0' device not found:"
788 "vendor 0x%x device 0x%x Func 0 (broken BIOS?)\n",
789 PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_I5000_BRANCH_0);
790
791 pci_dev_put(pvt->branchmap_werrors);
792 pci_dev_put(pvt->fsb_error_regs);
793 return 1;
794 }
795
796 pvt->branch_0 = pdev;
797
798 /* If this device claims to have more than 2 channels then
799 * fetch Branch 1's information
800 */
801 if (pvt->maxch >= CHANNELS_PER_BRANCH) {
802 pdev = NULL;
803 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
804 PCI_DEVICE_ID_I5000_BRANCH_1, pdev);
805
806 if (pdev == NULL) {
807 i5000_printk(KERN_ERR,
808 "MC: 'BRANCH 1' device not found:"
809 "vendor 0x%x device 0x%x Func 0 "
810 "(broken BIOS?)\n",
811 PCI_VENDOR_ID_INTEL,
812 PCI_DEVICE_ID_I5000_BRANCH_1);
813
814 pci_dev_put(pvt->branchmap_werrors);
815 pci_dev_put(pvt->fsb_error_regs);
816 pci_dev_put(pvt->branch_0);
817 return 1;
818 }
819
820 pvt->branch_1 = pdev;
821 }
822
823 return 0;
824}
825
826/******************************************************************************
827 * i5000_put_devices 'put' all the devices that we have
828 * reserved via 'get'
829 */
830static void i5000_put_devices(struct mem_ctl_info *mci)
831{
832 struct i5000_pvt *pvt;
833
834 pvt = (struct i5000_pvt *)mci->pvt_info;
835
836 pci_dev_put(pvt->branchmap_werrors); /* FUNC 1 */
837 pci_dev_put(pvt->fsb_error_regs); /* FUNC 2 */
838 pci_dev_put(pvt->branch_0); /* DEV 21 */
839
840 /* Only if more than 2 channels do we release the second branch */
841 if (pvt->maxch >= CHANNELS_PER_BRANCH) {
842 pci_dev_put(pvt->branch_1); /* DEV 22 */
843 }
844}
845
846/******************************************************************************
847 * determine_amb_resent
848 *
849 * the information is contained in NUM_MTRS different registers
850 * determineing which of the NUM_MTRS requires knowing
851 * which channel is in question
852 *
853 * 2 branches, each with 2 channels
854 * b0_ambpresent0 for channel '0'
855 * b0_ambpresent1 for channel '1'
856 * b1_ambpresent0 for channel '2'
857 * b1_ambpresent1 for channel '3'
858 */
859static int determine_amb_present_reg(struct i5000_pvt *pvt, int channel)
860{
861 int amb_present;
862
863 if (channel < CHANNELS_PER_BRANCH) {
864 if (channel & 0x1)
865 amb_present = pvt->b0_ambpresent1;
866 else
867 amb_present = pvt->b0_ambpresent0;
868 } else {
869 if (channel & 0x1)
870 amb_present = pvt->b1_ambpresent1;
871 else
872 amb_present = pvt->b1_ambpresent0;
873 }
874
875 return amb_present;
876}
877
878/******************************************************************************
879 * determine_mtr(pvt, csrow, channel)
880 *
881 * return the proper MTR register as determine by the csrow and channel desired
882 */
883static int determine_mtr(struct i5000_pvt *pvt, int csrow, int channel)
884{
885 int mtr;
886
887 if (channel < CHANNELS_PER_BRANCH)
888 mtr = pvt->b0_mtr[csrow >> 1];
889 else
890 mtr = pvt->b1_mtr[csrow >> 1];
891
892 return mtr;
893}
894
895/******************************************************************************
896 */
897static void decode_mtr(int slot_row, u16 mtr)
898{
899 int ans;
900
901 ans = MTR_DIMMS_PRESENT(mtr);
902
903 debugf2("\tMTR%d=0x%x: DIMMs are %s\n", slot_row, mtr,
904 ans ? "Present" : "NOT Present");
905 if (!ans)
906 return;
907
908 debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
909 debugf2("\t\tNUMBANK: %d bank(s)\n", MTR_DRAM_BANKS(mtr));
910 debugf2("\t\tNUMRANK: %s\n", MTR_DIMM_RANK(mtr) ? "double" : "single");
911 debugf2("\t\tNUMROW: %s\n", numrow_toString[MTR_DIMM_ROWS(mtr)]);
912 debugf2("\t\tNUMCOL: %s\n", numcol_toString[MTR_DIMM_COLS(mtr)]);
913}
914
915static void handle_channel(struct i5000_pvt *pvt, int csrow, int channel,
916 struct i5000_dimm_info *dinfo)
917{
918 int mtr;
919 int amb_present_reg;
920 int addrBits;
921
922 mtr = determine_mtr(pvt, csrow, channel);
923 if (MTR_DIMMS_PRESENT(mtr)) {
924 amb_present_reg = determine_amb_present_reg(pvt, channel);
925
926 /* Determine if there is a DIMM present in this DIMM slot */
927 if (amb_present_reg & (1 << (csrow >> 1))) {
928 dinfo->dual_rank = MTR_DIMM_RANK(mtr);
929
930 if (!((dinfo->dual_rank == 0) &&
931 ((csrow & 0x1) == 0x1))) {
932 /* Start with the number of bits for a Bank
933 * on the DRAM */
934 addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
935 /* Add thenumber of ROW bits */
936 addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
937 /* add the number of COLUMN bits */
938 addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
939
940 addrBits += 6; /* add 64 bits per DIMM */
941 addrBits -= 20; /* divide by 2^^20 */
942 addrBits -= 3; /* 8 bits per bytes */
943
944 dinfo->megabytes = 1 << addrBits;
945 }
946 }
947 }
948}
949
950/******************************************************************************
951 * calculate_dimm_size
952 *
953 * also will output a DIMM matrix map, if debug is enabled, for viewing
954 * how the DIMMs are populated
955 */
956static void calculate_dimm_size(struct i5000_pvt *pvt)
957{
958 struct i5000_dimm_info *dinfo;
959 int csrow, max_csrows;
960 char *p, *mem_buffer;
961 int space, n;
962 int channel;
963
964 /* ================= Generate some debug output ================= */
965 space = PAGE_SIZE;
966 mem_buffer = p = kmalloc(space, GFP_KERNEL);
967 if (p == NULL) {
968 i5000_printk(KERN_ERR, "MC: %s:%s() kmalloc() failed\n",
969 __FILE__, __func__);
970 return;
971 }
972
973 n = snprintf(p, space, "\n");
974 p += n;
975 space -= n;
976
977 /* Scan all the actual CSROWS (which is # of DIMMS * 2)
978 * and calculate the information for each DIMM
979 * Start with the highest csrow first, to display it first
980 * and work toward the 0th csrow
981 */
982 max_csrows = pvt->maxdimmperch * 2;
983 for (csrow = max_csrows - 1; csrow >= 0; csrow--) {
984
985 /* on an odd csrow, first output a 'boundary' marker,
986 * then reset the message buffer */
987 if (csrow & 0x1) {
988 n = snprintf(p, space, "---------------------------"
989 "--------------------------------");
990 p += n;
991 space -= n;
992 debugf2("%s\n", mem_buffer);
993 p = mem_buffer;
994 space = PAGE_SIZE;
995 }
996 n = snprintf(p, space, "csrow %2d ", csrow);
997 p += n;
998 space -= n;
999
1000 for (channel = 0; channel < pvt->maxch; channel++) {
1001 dinfo = &pvt->dimm_info[csrow][channel];
1002 handle_channel(pvt, csrow, channel, dinfo);
1003 n = snprintf(p, space, "%4d MB | ", dinfo->megabytes);
1004 p += n;
1005 space -= n;
1006 }
1007 n = snprintf(p, space, "\n");
1008 p += n;
1009 space -= n;
1010 }
1011
1012 /* Output the last bottom 'boundary' marker */
1013 n = snprintf(p, space, "---------------------------"
1014 "--------------------------------\n");
1015 p += n;
1016 space -= n;
1017
1018 /* now output the 'channel' labels */
1019 n = snprintf(p, space, " ");
1020 p += n;
1021 space -= n;
1022 for (channel = 0; channel < pvt->maxch; channel++) {
1023 n = snprintf(p, space, "channel %d | ", channel);
1024 p += n;
1025 space -= n;
1026 }
1027 n = snprintf(p, space, "\n");
1028 p += n;
1029 space -= n;
1030
1031 /* output the last message and free buffer */
1032 debugf2("%s\n", mem_buffer);
1033 kfree(mem_buffer);
1034}
1035
1036/******************************************************************************
1037 * i5000_get_mc_regs read in the necessary registers and
1038 * cache locally
1039 *
1040 * Fills in the private data members
1041 */
1042static void i5000_get_mc_regs(struct mem_ctl_info *mci)
1043{
1044 struct i5000_pvt *pvt;
1045 u32 actual_tolm;
1046 u16 limit;
1047 int slot_row;
1048 int maxch;
1049 int maxdimmperch;
1050 int way0, way1;
1051
1052 pvt = (struct i5000_pvt *)mci->pvt_info;
1053
1054 pci_read_config_dword(pvt->system_address, AMBASE,
1055 (u32 *) & pvt->ambase);
1056 pci_read_config_dword(pvt->system_address, AMBASE + sizeof(u32),
1057 ((u32 *) & pvt->ambase) + sizeof(u32));
1058
1059 maxdimmperch = pvt->maxdimmperch;
1060 maxch = pvt->maxch;
1061
1062 debugf2("AMBASE= 0x%lx MAXCH= %d MAX-DIMM-Per-CH= %d\n",
1063 (long unsigned int)pvt->ambase, pvt->maxch, pvt->maxdimmperch);
1064
1065 /* Get the Branch Map regs */
1066 pci_read_config_word(pvt->branchmap_werrors, TOLM, &pvt->tolm);
1067 pvt->tolm >>= 12;
1068 debugf2("\nTOLM (number of 256M regions) =%u (0x%x)\n", pvt->tolm,
1069 pvt->tolm);
1070
1071 actual_tolm = pvt->tolm << 28;
1072 debugf2("Actual TOLM byte addr=%u (0x%x)\n", actual_tolm, actual_tolm);
1073
1074 pci_read_config_word(pvt->branchmap_werrors, MIR0, &pvt->mir0);
1075 pci_read_config_word(pvt->branchmap_werrors, MIR1, &pvt->mir1);
1076 pci_read_config_word(pvt->branchmap_werrors, MIR2, &pvt->mir2);
1077
1078 /* Get the MIR[0-2] regs */
1079 limit = (pvt->mir0 >> 4) & 0x0FFF;
1080 way0 = pvt->mir0 & 0x1;
1081 way1 = pvt->mir0 & 0x2;
1082 debugf2("MIR0: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0);
1083 limit = (pvt->mir1 >> 4) & 0x0FFF;
1084 way0 = pvt->mir1 & 0x1;
1085 way1 = pvt->mir1 & 0x2;
1086 debugf2("MIR1: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0);
1087 limit = (pvt->mir2 >> 4) & 0x0FFF;
1088 way0 = pvt->mir2 & 0x1;
1089 way1 = pvt->mir2 & 0x2;
1090 debugf2("MIR2: limit= 0x%x WAY1= %u WAY0= %x\n", limit, way1, way0);
1091
1092 /* Get the MTR[0-3] regs */
1093 for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) {
1094 int where = MTR0 + (slot_row * sizeof(u32));
1095
1096 pci_read_config_word(pvt->branch_0, where,
1097 &pvt->b0_mtr[slot_row]);
1098
1099 debugf2("MTR%d where=0x%x B0 value=0x%x\n", slot_row, where,
1100 pvt->b0_mtr[slot_row]);
1101
1102 if (pvt->maxch >= CHANNELS_PER_BRANCH) {
1103 pci_read_config_word(pvt->branch_1, where,
1104 &pvt->b1_mtr[slot_row]);
1105 debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row,
1106 where, pvt->b0_mtr[slot_row]);
1107 } else {
1108 pvt->b1_mtr[slot_row] = 0;
1109 }
1110 }
1111
1112 /* Read and dump branch 0's MTRs */
1113 debugf2("\nMemory Technology Registers:\n");
1114 debugf2(" Branch 0:\n");
1115 for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) {
1116 decode_mtr(slot_row, pvt->b0_mtr[slot_row]);
1117 }
1118 pci_read_config_word(pvt->branch_0, AMB_PRESENT_0,
1119 &pvt->b0_ambpresent0);
1120 debugf2("\t\tAMB-Branch 0-present0 0x%x:\n", pvt->b0_ambpresent0);
1121 pci_read_config_word(pvt->branch_0, AMB_PRESENT_1,
1122 &pvt->b0_ambpresent1);
1123 debugf2("\t\tAMB-Branch 0-present1 0x%x:\n", pvt->b0_ambpresent1);
1124
1125 /* Only if we have 2 branchs (4 channels) */
1126 if (pvt->maxch < CHANNELS_PER_BRANCH) {
1127 pvt->b1_ambpresent0 = 0;
1128 pvt->b1_ambpresent1 = 0;
1129 } else {
1130 /* Read and dump branch 1's MTRs */
1131 debugf2(" Branch 1:\n");
1132 for (slot_row = 0; slot_row < NUM_MTRS; slot_row++) {
1133 decode_mtr(slot_row, pvt->b1_mtr[slot_row]);
1134 }
1135 pci_read_config_word(pvt->branch_1, AMB_PRESENT_0,
1136 &pvt->b1_ambpresent0);
1137 debugf2("\t\tAMB-Branch 1-present0 0x%x:\n",
1138 pvt->b1_ambpresent0);
1139 pci_read_config_word(pvt->branch_1, AMB_PRESENT_1,
1140 &pvt->b1_ambpresent1);
1141 debugf2("\t\tAMB-Branch 1-present1 0x%x:\n",
1142 pvt->b1_ambpresent1);
1143 }
1144
1145 /* Go and determine the size of each DIMM and place in an
1146 * orderly matrix */
1147 calculate_dimm_size(pvt);
1148}
1149
1150/******************************************************************************
1151 * i5000_init_csrows Initialize the 'csrows' table within
1152 * the mci control structure with the
1153 * addressing of memory.
1154 *
1155 * return:
1156 * 0 success
1157 * 1 no actual memory found on this MC
1158 */
1159static int i5000_init_csrows(struct mem_ctl_info *mci)
1160{
1161 struct i5000_pvt *pvt;
1162 struct csrow_info *p_csrow;
1163 int empty, channel_count;
1164 int max_csrows;
1165 int mtr;
1166 int csrow_megs;
1167 int channel;
1168 int csrow;
1169
1170 pvt = (struct i5000_pvt *)mci->pvt_info;
1171
1172 channel_count = pvt->maxch;
1173 max_csrows = pvt->maxdimmperch * 2;
1174
1175 empty = 1; /* Assume NO memory */
1176
1177 for (csrow = 0; csrow < max_csrows; csrow++) {
1178 p_csrow = &mci->csrows[csrow];
1179
1180 p_csrow->csrow_idx = csrow;
1181
1182 /* use branch 0 for the basis */
1183 mtr = pvt->b0_mtr[csrow >> 1];
1184
1185 /* if no DIMMS on this row, continue */
1186 if (!MTR_DIMMS_PRESENT(mtr))
1187 continue;
1188
1189 /* FAKE OUT VALUES, FIXME */
1190 p_csrow->first_page = 0 + csrow * 20;
1191 p_csrow->last_page = 9 + csrow * 20;
1192 p_csrow->page_mask = 0xFFF;
1193
1194 p_csrow->grain = 8;
1195
1196 csrow_megs = 0;
1197 for (channel = 0; channel < pvt->maxch; channel++) {
1198 csrow_megs += pvt->dimm_info[csrow][channel].megabytes;
1199 }
1200
1201 p_csrow->nr_pages = csrow_megs << 8;
1202
1203 /* Assume DDR2 for now */
1204 p_csrow->mtype = MEM_FB_DDR2;
1205
1206 /* ask what device type on this row */
1207 if (MTR_DRAM_WIDTH(mtr))
1208 p_csrow->dtype = DEV_X8;
1209 else
1210 p_csrow->dtype = DEV_X4;
1211
1212 p_csrow->edac_mode = EDAC_S8ECD8ED;
1213
1214 empty = 0;
1215 }
1216
1217 return empty;
1218}
1219
1220/******************************************************************************
1221 * i5000_enable_error_reporting
1222 * Turn on the memory reporting features of the hardware
1223 */
1224static void i5000_enable_error_reporting(struct mem_ctl_info *mci)
1225{
1226 struct i5000_pvt *pvt;
1227 u32 fbd_error_mask;
1228
1229 pvt = (struct i5000_pvt *)mci->pvt_info;
1230
1231 /* Read the FBD Error Mask Register */
1232 pci_read_config_dword(pvt->branchmap_werrors, EMASK_FBD,
1233 &fbd_error_mask);
1234
1235 /* Enable with a '0' */
1236 fbd_error_mask &= ~(ENABLE_EMASK_ALL);
1237
1238 pci_write_config_dword(pvt->branchmap_werrors, EMASK_FBD,
1239 fbd_error_mask);
1240}
1241
1242/******************************************************************************
1243 * i5000_get_dimm_and_channel_counts(pdev, &num_csrows, &num_channels)
1244 *
1245 * ask the device how many channels are present and how many CSROWS
1246 * as well
1247 */
1248static void i5000_get_dimm_and_channel_counts(struct pci_dev *pdev,
1249 int *num_dimms_per_channel,
1250 int *num_channels)
1251{
1252 u8 value;
1253
1254 /* Need to retrieve just how many channels and dimms per channel are
1255 * supported on this memory controller
1256 */
1257 pci_read_config_byte(pdev, MAXDIMMPERCH, &value);
1258 *num_dimms_per_channel = (int)value *2;
1259
1260 pci_read_config_byte(pdev, MAXCH, &value);
1261 *num_channels = (int)value;
1262}
1263
1264/******************************************************************************
1265 * i5000_probe1 Probe for ONE instance of device to see if it is
1266 * present.
1267 * return:
1268 * 0 for FOUND a device
1269 * < 0 for error code
1270 */
1271static int i5000_probe1(struct pci_dev *pdev, int dev_idx)
1272{
1273 struct mem_ctl_info *mci;
1274 struct i5000_pvt *pvt;
1275 int num_channels;
1276 int num_dimms_per_channel;
1277 int num_csrows;
1278
1279 debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n",
1280 __func__,
1281 pdev->bus->number,
1282 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
1283
1284 /* We only are looking for func 0 of the set */
1285 if (PCI_FUNC(pdev->devfn) != 0)
1286 return -ENODEV;
1287
1288 /* Ask the devices for the number of CSROWS and CHANNELS so
1289 * that we can calculate the memory resources, etc
1290 *
1291 * The Chipset will report what it can handle which will be greater
1292 * or equal to what the motherboard manufacturer will implement.
1293 *
1294 * As we don't have a motherboard identification routine to determine
1295 * actual number of slots/dimms per channel, we thus utilize the
1296 * resource as specified by the chipset. Thus, we might have
1297 * have more DIMMs per channel than actually on the mobo, but this
1298 * allows the driver to support upto the chipset max, without
1299 * some fancy mobo determination.
1300 */
1301 i5000_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel,
1302 &num_channels);
1303 num_csrows = num_dimms_per_channel * 2;
1304
1305 debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n",
1306 __func__, num_channels, num_dimms_per_channel, num_csrows);
1307
1308 /* allocate a new MC control structure */
1309 mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels);
1310
1311 if (mci == NULL)
1312 return -ENOMEM;
1313
1314 debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
1315
1316 mci->dev = &pdev->dev; /* record ptr to the generic device */
1317
1318 pvt = (struct i5000_pvt *)mci->pvt_info;
1319 pvt->system_address = pdev; /* Record this device in our private */
1320 pvt->maxch = num_channels;
1321 pvt->maxdimmperch = num_dimms_per_channel;
1322
1323 /* 'get' the pci devices we want to reserve for our use */
1324 if (i5000_get_devices(mci, dev_idx))
1325 goto fail0;
1326
1327 /* Time to get serious */
1328 i5000_get_mc_regs(mci); /* retrieve the hardware registers */
1329
1330 mci->mc_idx = 0;
1331 mci->mtype_cap = MEM_FLAG_FB_DDR2;
1332 mci->edac_ctl_cap = EDAC_FLAG_NONE;
1333 mci->edac_cap = EDAC_FLAG_NONE;
1334 mci->mod_name = "i5000_edac.c";
1335 mci->mod_ver = I5000_REVISION;
1336 mci->ctl_name = i5000_devs[dev_idx].ctl_name;
1337 mci->ctl_page_to_phys = NULL;
1338
1339 /* Set the function pointer to an actual operation function */
1340 mci->edac_check = i5000_check_error;
1341
1342 /* initialize the MC control structure 'csrows' table
1343 * with the mapping and control information */
1344 if (i5000_init_csrows(mci)) {
1345 debugf0("MC: Setting mci->edac_cap to EDAC_FLAG_NONE\n"
1346 " because i5000_init_csrows() returned nonzero "
1347 "value\n");
1348 mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */
1349 } else {
1350 debugf1("MC: Enable error reporting now\n");
1351 i5000_enable_error_reporting(mci);
1352 }
1353
1354 /* add this new MC control structure to EDAC's list of MCs */
1355 if (edac_mc_add_mc(mci, pvt->node_id)) {
1356 debugf0("MC: " __FILE__
1357 ": %s(): failed edac_mc_add_mc()\n", __func__);
1358 /* FIXME: perhaps some code should go here that disables error
1359 * reporting if we just enabled it
1360 */
1361 goto fail1;
1362 }
1363
1364 i5000_clear_error(mci);
1365
1366 return 0;
1367
1368 /* Error exit unwinding stack */
1369 fail1:
1370
1371 i5000_put_devices(mci);
1372
1373 fail0:
1374 edac_mc_free(mci);
1375 return -ENODEV;
1376}
1377
1378/******************************************************************************
1379 * i5000_init_one constructor for one instance of device
1380 *
1381 * returns:
1382 * negative on error
1383 * count (>= 0)
1384 */
1385static int __devinit i5000_init_one(struct pci_dev *pdev,
1386 const struct pci_device_id *id)
1387{
1388 int rc;
1389
1390 debugf0("MC: " __FILE__ ": %s()\n", __func__);
1391
1392 /* wake up device */
1393 rc = pci_enable_device(pdev);
1394 if (rc == -EIO)
1395 return rc;
1396
1397 /* now probe and enable the device */
1398 return i5000_probe1(pdev, id->driver_data);
1399}
1400
1401/**************************************************************************
1402 * i5000_remove_one destructor for one instance of device
1403 *
1404 */
1405static void __devexit i5000_remove_one(struct pci_dev *pdev)
1406{
1407 struct mem_ctl_info *mci;
1408
1409 debugf0(__FILE__ ": %s()\n", __func__);
1410
1411 if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
1412 return;
1413
1414 /* retrieve references to resources, and free those resources */
1415 i5000_put_devices(mci);
1416
1417 edac_mc_free(mci);
1418}
1419
1420/**************************************************************************
1421 * pci_device_id table for which devices we are looking for
1422 *
1423 * The "E500P" device is the first device supported.
1424 */
1425static const struct pci_device_id i5000_pci_tbl[] __devinitdata = {
1426 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I5000_DEV16),
1427 .driver_data = I5000P},
1428
1429 {0,} /* 0 terminated list. */
1430};
1431
1432MODULE_DEVICE_TABLE(pci, i5000_pci_tbl);
1433
1434/**************************************************************************
1435 * i5000_driver pci_driver structure for this module
1436 *
1437 */
1438static struct pci_driver i5000_driver = {
1439 .name = __stringify(KBUILD_BASENAME),
1440 .probe = i5000_init_one,
1441 .remove = __devexit_p(i5000_remove_one),
1442 .id_table = i5000_pci_tbl,
1443};
1444
1445/**************************************************************************
1446 * i5000_init Module entry function
1447 * Try to initialize this module for its devices
1448 */
1449static int __init i5000_init(void)
1450{
1451 int pci_rc;
1452
1453 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1454
1455 pci_rc = pci_register_driver(&i5000_driver);
1456
1457 return (pci_rc < 0) ? pci_rc : 0;
1458}
1459
1460/**************************************************************************
1461 * i5000_exit() Module exit function
1462 * Unregister the driver
1463 */
1464static void __exit i5000_exit(void)
1465{
1466 debugf2("MC: " __FILE__ ": %s()\n", __func__);
1467 pci_unregister_driver(&i5000_driver);
1468}
1469
1470module_init(i5000_init);
1471module_exit(i5000_exit);
1472
1473MODULE_LICENSE("GPL");
1474MODULE_AUTHOR
1475 ("Linux Networx (http://lnxi.com) Doug Thompson <norsk5@xmission.com>");
1476MODULE_DESCRIPTION("MC Driver for Intel I5000 memory controllers - "
1477 I5000_REVISION);