OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [edac/] [i5000_edac.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.