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