1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/pci.h>
21#include <linux/pci_ids.h>
22#include <linux/slab.h>
23#include <linux/edac.h>
24#include "edac_core.h"
25
26#define R82600_REVISION " Ver: 2.0.2 " __DATE__
27#define EDAC_MOD_STR "r82600_edac"
28
29#define r82600_printk(level, fmt, arg...) \
30 edac_printk(level, "r82600", fmt, ##arg)
31
32#define r82600_mc_printk(mci, level, fmt, arg...) \
33 edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg)
34
35
36
37
38
39
40
41
42
43
44
45#define R82600_NR_CSROWS 4
46#define R82600_NR_CHANS 1
47#define R82600_NR_DIMMS 4
48
49#define R82600_BRIDGE_ID 0x8200
50
51
52#define R82600_DRAMC 0x57
53
54
55
56
57
58
59
60
61
62
63
64
65
66#define R82600_SDRAMC 0x76
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90#define R82600_EAP 0x80
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124#define R82600_DRBA 0x60
125
126
127
128
129
130
131struct r82600_error_info {
132 u32 eapr;
133};
134
135static unsigned int disable_hardware_scrub;
136
137static struct edac_pci_ctl_info *r82600_pci;
138
139static void r82600_get_error_info(struct mem_ctl_info *mci,
140 struct r82600_error_info *info)
141{
142 struct pci_dev *pdev;
143
144 pdev = to_pci_dev(mci->dev);
145 pci_read_config_dword(pdev, R82600_EAP, &info->eapr);
146
147 if (info->eapr & BIT(0))
148
149 pci_write_bits32(pdev, R82600_EAP,
150 ((u32) BIT(0) & (u32) BIT(1)),
151 ((u32) BIT(0) & (u32) BIT(1)));
152
153 if (info->eapr & BIT(1))
154
155 pci_write_bits32(pdev, R82600_EAP,
156 ((u32) BIT(0) & (u32) BIT(1)),
157 ((u32) BIT(0) & (u32) BIT(1)));
158}
159
160static int r82600_process_error_info(struct mem_ctl_info *mci,
161 struct r82600_error_info *info,
162 int handle_errors)
163{
164 int error_found;
165 u32 eapaddr, page;
166 u32 syndrome;
167
168 error_found = 0;
169
170
171 eapaddr = ((info->eapr >> 12) & 0x7FFF) << 13;
172
173 syndrome = (info->eapr >> 4) & 0xFF;
174
175
176
177 page = eapaddr >> PAGE_SHIFT;
178
179 if (info->eapr & BIT(0)) {
180 error_found = 1;
181
182 if (handle_errors)
183 edac_mc_handle_ce(mci, page, 0,
184 syndrome,
185 edac_mc_find_csrow_by_page(mci, page),
186 0, mci->ctl_name);
187 }
188
189 if (info->eapr & BIT(1)) {
190 error_found = 1;
191
192 if (handle_errors)
193
194 edac_mc_handle_ue(mci, page, 0,
195 edac_mc_find_csrow_by_page(mci, page),
196 mci->ctl_name);
197 }
198
199 return error_found;
200}
201
202static void r82600_check(struct mem_ctl_info *mci)
203{
204 struct r82600_error_info info;
205
206 debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
207 r82600_get_error_info(mci, &info);
208 r82600_process_error_info(mci, &info, 1);
209}
210
211static inline int ecc_enabled(u8 dramcr)
212{
213 return dramcr & BIT(5);
214}
215
216static void r82600_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
217 u8 dramcr)
218{
219 struct csrow_info *csrow;
220 int index;
221 u8 drbar;
222 u32 row_high_limit, row_high_limit_last;
223 u32 reg_sdram, ecc_on, row_base;
224
225 ecc_on = ecc_enabled(dramcr);
226 reg_sdram = dramcr & BIT(4);
227 row_high_limit_last = 0;
228
229 for (index = 0; index < mci->nr_csrows; index++) {
230 csrow = &mci->csrows[index];
231
232
233 pci_read_config_byte(pdev, R82600_DRBA + index, &drbar);
234
235 debugf1("%s() Row=%d DRBA = %#0x\n", __func__, index, drbar);
236
237 row_high_limit = ((u32) drbar << 24);
238
239
240 debugf1("%s() Row=%d, Boundry Address=%#0x, Last = %#0x\n",
241 __func__, index, row_high_limit, row_high_limit_last);
242
243
244 if (row_high_limit == row_high_limit_last)
245 continue;
246
247 row_base = row_high_limit_last;
248
249 csrow->first_page = row_base >> PAGE_SHIFT;
250 csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
251 csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
252
253
254 csrow->grain = 1 << 14;
255 csrow->mtype = reg_sdram ? MEM_RDDR : MEM_DDR;
256
257 csrow->dtype = DEV_UNKNOWN;
258
259
260 csrow->edac_mode = ecc_on ? EDAC_SECDED : EDAC_NONE;
261 row_high_limit_last = row_high_limit;
262 }
263}
264
265static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
266{
267 struct mem_ctl_info *mci;
268 u8 dramcr;
269 u32 eapr;
270 u32 scrub_disabled;
271 u32 sdram_refresh_rate;
272 struct r82600_error_info discard;
273
274 debugf0("%s()\n", __func__);
275 pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
276 pci_read_config_dword(pdev, R82600_EAP, &eapr);
277 scrub_disabled = eapr & BIT(31);
278 sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
279 debugf2("%s(): sdram refresh rate = %#0x\n", __func__,
280 sdram_refresh_rate);
281 debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr);
282 mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS, 0);
283
284 if (mci == NULL)
285 return -ENOMEM;
286
287 debugf0("%s(): mci = %p\n", __func__, mci);
288 mci->dev = &pdev->dev;
289 mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
290 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
291
292
293
294
295
296
297
298
299 mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
300
301 if (ecc_enabled(dramcr)) {
302 if (scrub_disabled)
303 debugf3("%s(): mci = %p - Scrubbing disabled! EAP: "
304 "%#0x\n", __func__, mci, eapr);
305 } else
306 mci->edac_cap = EDAC_FLAG_NONE;
307
308 mci->mod_name = EDAC_MOD_STR;
309 mci->mod_ver = R82600_REVISION;
310 mci->ctl_name = "R82600";
311 mci->dev_name = pci_name(pdev);
312 mci->edac_check = r82600_check;
313 mci->ctl_page_to_phys = NULL;
314 r82600_init_csrows(mci, pdev, dramcr);
315 r82600_get_error_info(mci, &discard);
316
317
318
319
320 if (edac_mc_add_mc(mci)) {
321 debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
322 goto fail;
323 }
324
325
326
327 if (disable_hardware_scrub) {
328 debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n",
329 __func__);
330 pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31));
331 }
332
333
334 r82600_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR);
335 if (!r82600_pci) {
336 printk(KERN_WARNING
337 "%s(): Unable to create PCI control\n",
338 __func__);
339 printk(KERN_WARNING
340 "%s(): PCI error report via EDAC not setup\n",
341 __func__);
342 }
343
344 debugf3("%s(): success\n", __func__);
345 return 0;
346
347fail:
348 edac_mc_free(mci);
349 return -ENODEV;
350}
351
352
353static int __devinit r82600_init_one(struct pci_dev *pdev,
354 const struct pci_device_id *ent)
355{
356 debugf0("%s()\n", __func__);
357
358
359 return r82600_probe1(pdev, ent->driver_data);
360}
361
362static void __devexit r82600_remove_one(struct pci_dev *pdev)
363{
364 struct mem_ctl_info *mci;
365
366 debugf0("%s()\n", __func__);
367
368 if (r82600_pci)
369 edac_pci_release_generic_ctl(r82600_pci);
370
371 if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL)
372 return;
373
374 edac_mc_free(mci);
375}
376
377static const struct pci_device_id r82600_pci_tbl[] __devinitdata = {
378 {
379 PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)
380 },
381 {
382 0,
383 }
384};
385
386MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
387
388static struct pci_driver r82600_driver = {
389 .name = EDAC_MOD_STR,
390 .probe = r82600_init_one,
391 .remove = __devexit_p(r82600_remove_one),
392 .id_table = r82600_pci_tbl,
393};
394
395static int __init r82600_init(void)
396{
397
398 opstate_init();
399
400 return pci_register_driver(&r82600_driver);
401}
402
403static void __exit r82600_exit(void)
404{
405 pci_unregister_driver(&r82600_driver);
406}
407
408module_init(r82600_init);
409module_exit(r82600_exit);
410
411MODULE_LICENSE("GPL");
412MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
413 "on behalf of EADS Astrium");
414MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
415
416module_param(disable_hardware_scrub, bool, 0644);
417MODULE_PARM_DESC(disable_hardware_scrub,
418 "If set, disable the chipset's automatic scrub for CEs");
419
420module_param(edac_op_state, int, 0444);
421MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI");
422