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