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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Intel 82860 Memory Controller kernel module
3
 * (C) 2005 Red Hat (http://www.redhat.com)
4
 * This file may be distributed under the terms of the
5
 * GNU General Public License.
6
 *
7
 * Written by Ben Woodard <woodard@redhat.com>
8
 * shamelessly copied from and based upon the edac_i82875 driver
9
 * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
10
 */
11
 
12
#include <linux/module.h>
13
#include <linux/init.h>
14
#include <linux/pci.h>
15
#include <linux/pci_ids.h>
16
#include <linux/slab.h>
17
#include "edac_core.h"
18
 
19
#define  I82860_REVISION " Ver: 2.0.2 " __DATE__
20
#define EDAC_MOD_STR    "i82860_edac"
21
 
22
#define i82860_printk(level, fmt, arg...) \
23
        edac_printk(level, "i82860", fmt, ##arg)
24
 
25
#define i82860_mc_printk(mci, level, fmt, arg...) \
26
        edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
27
 
28
#ifndef PCI_DEVICE_ID_INTEL_82860_0
29
#define PCI_DEVICE_ID_INTEL_82860_0     0x2531
30
#endif                          /* PCI_DEVICE_ID_INTEL_82860_0 */
31
 
32
#define I82860_MCHCFG 0x50
33
#define I82860_GBA 0x60
34
#define I82860_GBA_MASK 0x7FF
35
#define I82860_GBA_SHIFT 24
36
#define I82860_ERRSTS 0xC8
37
#define I82860_EAP 0xE4
38
#define I82860_DERRCTL_STS 0xE2
39
 
40
enum i82860_chips {
41
        I82860 = 0,
42
};
43
 
44
struct i82860_dev_info {
45
        const char *ctl_name;
46
};
47
 
48
struct i82860_error_info {
49
        u16 errsts;
50
        u32 eap;
51
        u16 derrsyn;
52
        u16 errsts2;
53
};
54
 
55
static const struct i82860_dev_info i82860_devs[] = {
56
        [I82860] = {
57
                .ctl_name = "i82860"},
58
};
59
 
60
static struct pci_dev *mci_pdev;        /* init dev: in case that AGP code
61
                                         * has already registered driver
62
                                         */
63
static struct edac_pci_ctl_info *i82860_pci;
64
 
65
static void i82860_get_error_info(struct mem_ctl_info *mci,
66
                                struct i82860_error_info *info)
67
{
68
        struct pci_dev *pdev;
69
 
70
        pdev = to_pci_dev(mci->dev);
71
 
72
        /*
73
         * This is a mess because there is no atomic way to read all the
74
         * registers at once and the registers can transition from CE being
75
         * overwritten by UE.
76
         */
77
        pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts);
78
        pci_read_config_dword(pdev, I82860_EAP, &info->eap);
79
        pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
80
        pci_read_config_word(pdev, I82860_ERRSTS, &info->errsts2);
81
 
82
        pci_write_bits16(pdev, I82860_ERRSTS, 0x0003, 0x0003);
83
 
84
        /*
85
         * If the error is the same for both reads then the first set of reads
86
         * is valid.  If there is a change then there is a CE no info and the
87
         * second set of reads is valid and should be UE info.
88
         */
89
        if (!(info->errsts2 & 0x0003))
90
                return;
91
 
92
        if ((info->errsts ^ info->errsts2) & 0x0003) {
93
                pci_read_config_dword(pdev, I82860_EAP, &info->eap);
94
                pci_read_config_word(pdev, I82860_DERRCTL_STS, &info->derrsyn);
95
        }
96
}
97
 
98
static int i82860_process_error_info(struct mem_ctl_info *mci,
99
                                struct i82860_error_info *info,
100
                                int handle_errors)
101
{
102
        int row;
103
 
104
        if (!(info->errsts2 & 0x0003))
105
                return 0;
106
 
107
        if (!handle_errors)
108
                return 1;
109
 
110
        if ((info->errsts ^ info->errsts2) & 0x0003) {
111
                edac_mc_handle_ce_no_info(mci, "UE overwrote CE");
112
                info->errsts = info->errsts2;
113
        }
114
 
115
        info->eap >>= PAGE_SHIFT;
116
        row = edac_mc_find_csrow_by_page(mci, info->eap);
117
 
118
        if (info->errsts & 0x0002)
119
                edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
120
        else
121
                edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0,
122
                                "i82860 UE");
123
 
124
        return 1;
125
}
126
 
127
static void i82860_check(struct mem_ctl_info *mci)
128
{
129
        struct i82860_error_info info;
130
 
131
        debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
132
        i82860_get_error_info(mci, &info);
133
        i82860_process_error_info(mci, &info, 1);
134
}
135
 
136
static void i82860_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev)
137
{
138
        unsigned long last_cumul_size;
139
        u16 mchcfg_ddim;        /* DRAM Data Integrity Mode 0=none, 2=edac */
140
        u16 value;
141
        u32 cumul_size;
142
        struct csrow_info *csrow;
143
        int index;
144
 
145
        pci_read_config_word(pdev, I82860_MCHCFG, &mchcfg_ddim);
146
        mchcfg_ddim = mchcfg_ddim & 0x180;
147
        last_cumul_size = 0;
148
 
149
        /* The group row boundary (GRA) reg values are boundary address
150
         * for each DRAM row with a granularity of 16MB.  GRA regs are
151
         * cumulative; therefore GRA15 will contain the total memory contained
152
         * in all eight rows.
153
         */
154
        for (index = 0; index < mci->nr_csrows; index++) {
155
                csrow = &mci->csrows[index];
156
                pci_read_config_word(pdev, I82860_GBA + index * 2, &value);
157
                cumul_size = (value & I82860_GBA_MASK) <<
158
                        (I82860_GBA_SHIFT - PAGE_SHIFT);
159
                debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
160
                        cumul_size);
161
 
162
                if (cumul_size == last_cumul_size)
163
                        continue;       /* not populated */
164
 
165
                csrow->first_page = last_cumul_size;
166
                csrow->last_page = cumul_size - 1;
167
                csrow->nr_pages = cumul_size - last_cumul_size;
168
                last_cumul_size = cumul_size;
169
                csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
170
                csrow->mtype = MEM_RMBS;
171
                csrow->dtype = DEV_UNKNOWN;
172
                csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
173
        }
174
}
175
 
176
static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
177
{
178
        struct mem_ctl_info *mci;
179
        struct i82860_error_info discard;
180
 
181
        /* RDRAM has channels but these don't map onto the abstractions that
182
           edac uses.
183
           The device groups from the GRA registers seem to map reasonably
184
           well onto the notion of a chip select row.
185
           There are 16 GRA registers and since the name is associated with
186
           the channel and the GRA registers map to physical devices so we are
187
           going to make 1 channel for group.
188
         */
189
        mci = edac_mc_alloc(0, 16, 1, 0);
190
 
191
        if (!mci)
192
                return -ENOMEM;
193
 
194
        debugf3("%s(): init mci\n", __func__);
195
        mci->dev = &pdev->dev;
196
        mci->mtype_cap = MEM_FLAG_DDR;
197
        mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
198
        /* I"m not sure about this but I think that all RDRAM is SECDED */
199
        mci->edac_cap = EDAC_FLAG_SECDED;
200
        mci->mod_name = EDAC_MOD_STR;
201
        mci->mod_ver = I82860_REVISION;
202
        mci->ctl_name = i82860_devs[dev_idx].ctl_name;
203
        mci->dev_name = pci_name(pdev);
204
        mci->edac_check = i82860_check;
205
        mci->ctl_page_to_phys = NULL;
206
        i82860_init_csrows(mci, pdev);
207
        i82860_get_error_info(mci, &discard);   /* clear counters */
208
 
209
        /* Here we assume that we will never see multiple instances of this
210
         * type of memory controller.  The ID is therefore hardcoded to 0.
211
         */
212
        if (edac_mc_add_mc(mci)) {
213
                debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
214
                goto fail;
215
        }
216
 
217
        /* allocating generic PCI control info */
218
        i82860_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
219
        if (!i82860_pci) {
220
                printk(KERN_WARNING
221
                        "%s(): Unable to create PCI control\n",
222
                        __func__);
223
                printk(KERN_WARNING
224
                        "%s(): PCI error report via EDAC not setup\n",
225
                        __func__);
226
        }
227
 
228
        /* get this far and it's successful */
229
        debugf3("%s(): success\n", __func__);
230
 
231
        return 0;
232
 
233
fail:
234
        edac_mc_free(mci);
235
        return -ENODEV;
236
}
237
 
238
/* returns count (>= 0), or negative on error */
239
static int __devinit i82860_init_one(struct pci_dev *pdev,
240
                                const struct pci_device_id *ent)
241
{
242
        int rc;
243
 
244
        debugf0("%s()\n", __func__);
245
        i82860_printk(KERN_INFO, "i82860 init one\n");
246
 
247
        if (pci_enable_device(pdev) < 0)
248
                return -EIO;
249
 
250
        rc = i82860_probe1(pdev, ent->driver_data);
251
 
252
        if (rc == 0)
253
                mci_pdev = pci_dev_get(pdev);
254
 
255
        return rc;
256
}
257
 
258
static void __devexit i82860_remove_one(struct pci_dev *pdev)
259
{
260
        struct mem_ctl_info *mci;
261
 
262
        debugf0("%s()\n", __func__);
263
 
264
        if (i82860_pci)
265
                edac_pci_release_generic_ctl(i82860_pci);
266
 
267
        if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
268
                return;
269
 
270
        edac_mc_free(mci);
271
}
272
 
273
static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
274
        {
275
         PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
276
         I82860},
277
        {
278
         0,
279
         }                      /* 0 terminated list. */
280
};
281
 
282
MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
283
 
284
static struct pci_driver i82860_driver = {
285
        .name = EDAC_MOD_STR,
286
        .probe = i82860_init_one,
287
        .remove = __devexit_p(i82860_remove_one),
288
        .id_table = i82860_pci_tbl,
289
};
290
 
291
static int __init i82860_init(void)
292
{
293
        int pci_rc;
294
 
295
        debugf3("%s()\n", __func__);
296
 
297
        if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
298
                goto fail0;
299
 
300
        if (!mci_pdev) {
301
                mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
302
                                        PCI_DEVICE_ID_INTEL_82860_0, NULL);
303
 
304
                if (mci_pdev == NULL) {
305
                        debugf0("860 pci_get_device fail\n");
306
                        pci_rc = -ENODEV;
307
                        goto fail1;
308
                }
309
 
310
                pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
311
 
312
                if (pci_rc < 0) {
313
                        debugf0("860 init fail\n");
314
                        pci_rc = -ENODEV;
315
                        goto fail1;
316
                }
317
        }
318
 
319
        return 0;
320
 
321
fail1:
322
        pci_unregister_driver(&i82860_driver);
323
 
324
fail0:
325
        if (mci_pdev != NULL)
326
                pci_dev_put(mci_pdev);
327
 
328
        return pci_rc;
329
}
330
 
331
static void __exit i82860_exit(void)
332
{
333
        debugf3("%s()\n", __func__);
334
 
335
        pci_unregister_driver(&i82860_driver);
336
 
337
        if (mci_pdev != NULL)
338
                pci_dev_put(mci_pdev);
339
}
340
 
341
module_init(i82860_init);
342
module_exit(i82860_exit);
343
 
344
MODULE_LICENSE("GPL");
345
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
346
                "Ben Woodard <woodard@redhat.com>");
347
MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");

powered by: WebSVN 2.1.0

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