Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
[linux-2.6] / drivers / edac / mv64x60_edac.c
1 /*
2  * Marvell MV64x60 Memory Controller kernel module for PPC platforms
3  *
4  * Author: Dave Jiang <djiang@mvista.com>
5  *
6  * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
7  * the terms of the GNU General Public License version 2. This program
8  * is licensed "as is" without any warranty of any kind, whether express
9  * or implied.
10  *
11  */
12
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
16 #include <linux/interrupt.h>
17 #include <linux/io.h>
18 #include <linux/edac.h>
19
20 #include "edac_core.h"
21 #include "edac_module.h"
22 #include "mv64x60_edac.h"
23
24 static const char *mv64x60_ctl_name = "MV64x60";
25 static int edac_dev_idx;
26 static int edac_pci_idx;
27 static int edac_mc_idx;
28
29 /*********************** PCI err device **********************************/
30 #ifdef CONFIG_PCI
31 static void mv64x60_pci_check(struct edac_pci_ctl_info *pci)
32 {
33         struct mv64x60_pci_pdata *pdata = pci->pvt_info;
34         u32 cause;
35
36         cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
37         if (!cause)
38                 return;
39
40         printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose);
41         printk(KERN_ERR "Cause register: 0x%08x\n", cause);
42         printk(KERN_ERR "Address Low: 0x%08x\n",
43                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO));
44         printk(KERN_ERR "Address High: 0x%08x\n",
45                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI));
46         printk(KERN_ERR "Attribute: 0x%08x\n",
47                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR));
48         printk(KERN_ERR "Command: 0x%08x\n",
49                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD));
50         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause);
51
52         if (cause & MV64X60_PCI_PE_MASK)
53                 edac_pci_handle_pe(pci, pci->ctl_name);
54
55         if (!(cause & MV64X60_PCI_PE_MASK))
56                 edac_pci_handle_npe(pci, pci->ctl_name);
57 }
58
59 static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
60 {
61         struct edac_pci_ctl_info *pci = dev_id;
62         struct mv64x60_pci_pdata *pdata = pci->pvt_info;
63         u32 val;
64
65         val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
66         if (!val)
67                 return IRQ_NONE;
68
69         mv64x60_pci_check(pci);
70
71         return IRQ_HANDLED;
72 }
73
74 static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
75 {
76         struct edac_pci_ctl_info *pci;
77         struct mv64x60_pci_pdata *pdata;
78         struct resource *r;
79         int res = 0;
80
81         if (!devres_open_group(&pdev->dev, mv64x60_pci_err_probe, GFP_KERNEL))
82                 return -ENOMEM;
83
84         pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mv64x60_pci_err");
85         if (!pci)
86                 return -ENOMEM;
87
88         pdata = pci->pvt_info;
89
90         pdata->pci_hose = pdev->id;
91         pdata->name = "mpc85xx_pci_err";
92         pdata->irq = NO_IRQ;
93         platform_set_drvdata(pdev, pci);
94         pci->dev = &pdev->dev;
95         pci->dev_name = pdev->dev.bus_id;
96         pci->mod_name = EDAC_MOD_STR;
97         pci->ctl_name = pdata->name;
98
99         if (edac_op_state == EDAC_OPSTATE_POLL)
100                 pci->edac_check = mv64x60_pci_check;
101
102         pdata->edac_idx = edac_pci_idx++;
103
104         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
105         if (!r) {
106                 printk(KERN_ERR "%s: Unable to get resource for "
107                        "PCI err regs\n", __func__);
108                 res = -ENOENT;
109                 goto err;
110         }
111
112         if (!devm_request_mem_region(&pdev->dev,
113                                      r->start,
114                                      r->end - r->start + 1,
115                                      pdata->name)) {
116                 printk(KERN_ERR "%s: Error while requesting mem region\n",
117                        __func__);
118                 res = -EBUSY;
119                 goto err;
120         }
121
122         pdata->pci_vbase = devm_ioremap(&pdev->dev,
123                                         r->start,
124                                         r->end - r->start + 1);
125         if (!pdata->pci_vbase) {
126                 printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
127                 res = -ENOMEM;
128                 goto err;
129         }
130
131         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0);
132         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0);
133         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK,
134                  MV64X60_PCIx_ERR_MASK_VAL);
135
136         if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
137                 debugf3("%s(): failed edac_pci_add_device()\n", __func__);
138                 goto err;
139         }
140
141         if (edac_op_state == EDAC_OPSTATE_INT) {
142                 pdata->irq = platform_get_irq(pdev, 0);
143                 res = devm_request_irq(&pdev->dev,
144                                        pdata->irq,
145                                        mv64x60_pci_isr,
146                                        IRQF_DISABLED,
147                                        "[EDAC] PCI err",
148                                        pci);
149                 if (res < 0) {
150                         printk(KERN_ERR "%s: Unable to request irq %d for "
151                                "MV64x60 PCI ERR\n", __func__, pdata->irq);
152                         res = -ENODEV;
153                         goto err2;
154                 }
155                 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n",
156                        pdata->irq);
157         }
158
159         devres_remove_group(&pdev->dev, mv64x60_pci_err_probe);
160
161         /* get this far and it's successful */
162         debugf3("%s(): success\n", __func__);
163
164         return 0;
165
166 err2:
167         edac_pci_del_device(&pdev->dev);
168 err:
169         edac_pci_free_ctl_info(pci);
170         devres_release_group(&pdev->dev, mv64x60_pci_err_probe);
171         return res;
172 }
173
174 static int mv64x60_pci_err_remove(struct platform_device *pdev)
175 {
176         struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
177
178         debugf0("%s()\n", __func__);
179
180         edac_pci_del_device(&pdev->dev);
181
182         edac_pci_free_ctl_info(pci);
183
184         return 0;
185 }
186
187 static struct platform_driver mv64x60_pci_err_driver = {
188         .probe = mv64x60_pci_err_probe,
189         .remove = __devexit_p(mv64x60_pci_err_remove),
190         .driver = {
191                    .name = "mv64x60_pci_err",
192         }
193 };
194
195 #endif /* CONFIG_PCI */
196
197 /*********************** SRAM err device **********************************/
198 static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev)
199 {
200         struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
201         u32 cause;
202
203         cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
204         if (!cause)
205                 return;
206
207         printk(KERN_ERR "Error in internal SRAM\n");
208         printk(KERN_ERR "Cause register: 0x%08x\n", cause);
209         printk(KERN_ERR "Address Low: 0x%08x\n",
210                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO));
211         printk(KERN_ERR "Address High: 0x%08x\n",
212                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI));
213         printk(KERN_ERR "Data Low: 0x%08x\n",
214                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO));
215         printk(KERN_ERR "Data High: 0x%08x\n",
216                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI));
217         printk(KERN_ERR "Parity: 0x%08x\n",
218                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY));
219         out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
220
221         edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
222 }
223
224 static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id)
225 {
226         struct edac_device_ctl_info *edac_dev = dev_id;
227         struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
228         u32 cause;
229
230         cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
231         if (!cause)
232                 return IRQ_NONE;
233
234         mv64x60_sram_check(edac_dev);
235
236         return IRQ_HANDLED;
237 }
238
239 static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev)
240 {
241         struct edac_device_ctl_info *edac_dev;
242         struct mv64x60_sram_pdata *pdata;
243         struct resource *r;
244         int res = 0;
245
246         if (!devres_open_group(&pdev->dev, mv64x60_sram_err_probe, GFP_KERNEL))
247                 return -ENOMEM;
248
249         edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
250                                               "sram", 1, NULL, 0, 0, NULL, 0,
251                                               edac_dev_idx);
252         if (!edac_dev) {
253                 devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
254                 return -ENOMEM;
255         }
256
257         pdata = edac_dev->pvt_info;
258         pdata->name = "mv64x60_sram_err";
259         pdata->irq = NO_IRQ;
260         edac_dev->dev = &pdev->dev;
261         platform_set_drvdata(pdev, edac_dev);
262         edac_dev->dev_name = pdev->dev.bus_id;
263
264         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
265         if (!r) {
266                 printk(KERN_ERR "%s: Unable to get resource for "
267                        "SRAM err regs\n", __func__);
268                 res = -ENOENT;
269                 goto err;
270         }
271
272         if (!devm_request_mem_region(&pdev->dev,
273                                      r->start,
274                                      r->end - r->start + 1,
275                                      pdata->name)) {
276                 printk(KERN_ERR "%s: Error while request mem region\n",
277                        __func__);
278                 res = -EBUSY;
279                 goto err;
280         }
281
282         pdata->sram_vbase = devm_ioremap(&pdev->dev,
283                                          r->start,
284                                          r->end - r->start + 1);
285         if (!pdata->sram_vbase) {
286                 printk(KERN_ERR "%s: Unable to setup SRAM err regs\n",
287                        __func__);
288                 res = -ENOMEM;
289                 goto err;
290         }
291
292         /* setup SRAM err registers */
293         out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
294
295         edac_dev->mod_name = EDAC_MOD_STR;
296         edac_dev->ctl_name = pdata->name;
297
298         if (edac_op_state == EDAC_OPSTATE_POLL)
299                 edac_dev->edac_check = mv64x60_sram_check;
300
301         pdata->edac_idx = edac_dev_idx++;
302
303         if (edac_device_add_device(edac_dev) > 0) {
304                 debugf3("%s(): failed edac_device_add_device()\n", __func__);
305                 goto err;
306         }
307
308         if (edac_op_state == EDAC_OPSTATE_INT) {
309                 pdata->irq = platform_get_irq(pdev, 0);
310                 res = devm_request_irq(&pdev->dev,
311                                        pdata->irq,
312                                        mv64x60_sram_isr,
313                                        IRQF_DISABLED,
314                                        "[EDAC] SRAM err",
315                                        edac_dev);
316                 if (res < 0) {
317                         printk(KERN_ERR
318                                "%s: Unable to request irq %d for "
319                                "MV64x60 SRAM ERR\n", __func__, pdata->irq);
320                         res = -ENODEV;
321                         goto err2;
322                 }
323
324                 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for SRAM Err\n",
325                        pdata->irq);
326         }
327
328         devres_remove_group(&pdev->dev, mv64x60_sram_err_probe);
329
330         /* get this far and it's successful */
331         debugf3("%s(): success\n", __func__);
332
333         return 0;
334
335 err2:
336         edac_device_del_device(&pdev->dev);
337 err:
338         devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
339         edac_device_free_ctl_info(edac_dev);
340         return res;
341 }
342
343 static int mv64x60_sram_err_remove(struct platform_device *pdev)
344 {
345         struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
346
347         debugf0("%s()\n", __func__);
348
349         edac_device_del_device(&pdev->dev);
350         edac_device_free_ctl_info(edac_dev);
351
352         return 0;
353 }
354
355 static struct platform_driver mv64x60_sram_err_driver = {
356         .probe = mv64x60_sram_err_probe,
357         .remove = mv64x60_sram_err_remove,
358         .driver = {
359                    .name = "mv64x60_sram_err",
360         }
361 };
362
363 /*********************** CPU err device **********************************/
364 static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
365 {
366         struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
367         u32 cause;
368
369         cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
370             MV64x60_CPU_CAUSE_MASK;
371         if (!cause)
372                 return;
373
374         printk(KERN_ERR "Error on CPU interface\n");
375         printk(KERN_ERR "Cause register: 0x%08x\n", cause);
376         printk(KERN_ERR "Address Low: 0x%08x\n",
377                in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO));
378         printk(KERN_ERR "Address High: 0x%08x\n",
379                in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI));
380         printk(KERN_ERR "Data Low: 0x%08x\n",
381                in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO));
382         printk(KERN_ERR "Data High: 0x%08x\n",
383                in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI));
384         printk(KERN_ERR "Parity: 0x%08x\n",
385                in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY));
386         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
387
388         edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
389 }
390
391 static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id)
392 {
393         struct edac_device_ctl_info *edac_dev = dev_id;
394         struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
395         u32 cause;
396
397         cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
398             MV64x60_CPU_CAUSE_MASK;
399         if (!cause)
400                 return IRQ_NONE;
401
402         mv64x60_cpu_check(edac_dev);
403
404         return IRQ_HANDLED;
405 }
406
407 static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev)
408 {
409         struct edac_device_ctl_info *edac_dev;
410         struct resource *r;
411         struct mv64x60_cpu_pdata *pdata;
412         int res = 0;
413
414         if (!devres_open_group(&pdev->dev, mv64x60_cpu_err_probe, GFP_KERNEL))
415                 return -ENOMEM;
416
417         edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
418                                               "cpu", 1, NULL, 0, 0, NULL, 0,
419                                               edac_dev_idx);
420         if (!edac_dev) {
421                 devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
422                 return -ENOMEM;
423         }
424
425         pdata = edac_dev->pvt_info;
426         pdata->name = "mv64x60_cpu_err";
427         pdata->irq = NO_IRQ;
428         edac_dev->dev = &pdev->dev;
429         platform_set_drvdata(pdev, edac_dev);
430         edac_dev->dev_name = pdev->dev.bus_id;
431
432         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
433         if (!r) {
434                 printk(KERN_ERR "%s: Unable to get resource for "
435                        "CPU err regs\n", __func__);
436                 res = -ENOENT;
437                 goto err;
438         }
439
440         if (!devm_request_mem_region(&pdev->dev,
441                                      r->start,
442                                      r->end - r->start + 1,
443                                      pdata->name)) {
444                 printk(KERN_ERR "%s: Error while requesting mem region\n",
445                        __func__);
446                 res = -EBUSY;
447                 goto err;
448         }
449
450         pdata->cpu_vbase[0] = devm_ioremap(&pdev->dev,
451                                            r->start,
452                                            r->end - r->start + 1);
453         if (!pdata->cpu_vbase[0]) {
454                 printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
455                 res = -ENOMEM;
456                 goto err;
457         }
458
459         r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
460         if (!r) {
461                 printk(KERN_ERR "%s: Unable to get resource for "
462                        "CPU err regs\n", __func__);
463                 res = -ENOENT;
464                 goto err;
465         }
466
467         if (!devm_request_mem_region(&pdev->dev,
468                                      r->start,
469                                      r->end - r->start + 1,
470                                      pdata->name)) {
471                 printk(KERN_ERR "%s: Error while requesting mem region\n",
472                        __func__);
473                 res = -EBUSY;
474                 goto err;
475         }
476
477         pdata->cpu_vbase[1] = devm_ioremap(&pdev->dev,
478                                            r->start,
479                                            r->end - r->start + 1);
480         if (!pdata->cpu_vbase[1]) {
481                 printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
482                 res = -ENOMEM;
483                 goto err;
484         }
485
486         /* setup CPU err registers */
487         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
488         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0);
489         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff);
490
491         edac_dev->mod_name = EDAC_MOD_STR;
492         edac_dev->ctl_name = pdata->name;
493         if (edac_op_state == EDAC_OPSTATE_POLL)
494                 edac_dev->edac_check = mv64x60_cpu_check;
495
496         pdata->edac_idx = edac_dev_idx++;
497
498         if (edac_device_add_device(edac_dev) > 0) {
499                 debugf3("%s(): failed edac_device_add_device()\n", __func__);
500                 goto err;
501         }
502
503         if (edac_op_state == EDAC_OPSTATE_INT) {
504                 pdata->irq = platform_get_irq(pdev, 0);
505                 res = devm_request_irq(&pdev->dev,
506                                        pdata->irq,
507                                        mv64x60_cpu_isr,
508                                        IRQF_DISABLED,
509                                        "[EDAC] CPU err",
510                                        edac_dev);
511                 if (res < 0) {
512                         printk(KERN_ERR
513                                "%s: Unable to request irq %d for MV64x60 "
514                                "CPU ERR\n", __func__, pdata->irq);
515                         res = -ENODEV;
516                         goto err2;
517                 }
518
519                 printk(KERN_INFO EDAC_MOD_STR
520                        " acquired irq %d for CPU Err\n", pdata->irq);
521         }
522
523         devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe);
524
525         /* get this far and it's successful */
526         debugf3("%s(): success\n", __func__);
527
528         return 0;
529
530 err2:
531         edac_device_del_device(&pdev->dev);
532 err:
533         devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
534         edac_device_free_ctl_info(edac_dev);
535         return res;
536 }
537
538 static int mv64x60_cpu_err_remove(struct platform_device *pdev)
539 {
540         struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
541
542         debugf0("%s()\n", __func__);
543
544         edac_device_del_device(&pdev->dev);
545         edac_device_free_ctl_info(edac_dev);
546         return 0;
547 }
548
549 static struct platform_driver mv64x60_cpu_err_driver = {
550         .probe = mv64x60_cpu_err_probe,
551         .remove = mv64x60_cpu_err_remove,
552         .driver = {
553                    .name = "mv64x60_cpu_err",
554         }
555 };
556
557 /*********************** DRAM err device **********************************/
558
559 static void mv64x60_mc_check(struct mem_ctl_info *mci)
560 {
561         struct mv64x60_mc_pdata *pdata = mci->pvt_info;
562         u32 reg;
563         u32 err_addr;
564         u32 sdram_ecc;
565         u32 comp_ecc;
566         u32 syndrome;
567
568         reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
569         if (!reg)
570                 return;
571
572         err_addr = reg & ~0x3;
573         sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD);
574         comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC);
575         syndrome = sdram_ecc ^ comp_ecc;
576
577         /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */
578         if (!(reg & 0x1))
579                 edac_mc_handle_ce(mci, err_addr >> PAGE_SHIFT,
580                                   err_addr & PAGE_MASK, syndrome, 0, 0,
581                                   mci->ctl_name);
582         else    /* 2 bit error, UE */
583                 edac_mc_handle_ue(mci, err_addr >> PAGE_SHIFT,
584                                   err_addr & PAGE_MASK, 0, mci->ctl_name);
585
586         /* clear the error */
587         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
588 }
589
590 static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
591 {
592         struct mem_ctl_info *mci = dev_id;
593         struct mv64x60_mc_pdata *pdata = mci->pvt_info;
594         u32 reg;
595
596         reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
597         if (!reg)
598                 return IRQ_NONE;
599
600         /* writing 0's to the ECC err addr in check function clears irq */
601         mv64x60_mc_check(mci);
602
603         return IRQ_HANDLED;
604 }
605
606 static void get_total_mem(struct mv64x60_mc_pdata *pdata)
607 {
608         struct device_node *np = NULL;
609         const unsigned int *reg;
610
611         np = of_find_node_by_type(NULL, "memory");
612         if (!np)
613                 return;
614
615         reg = get_property(np, "reg", NULL);
616
617         pdata->total_mem = reg[1];
618 }
619
620 static void mv64x60_init_csrows(struct mem_ctl_info *mci,
621                                 struct mv64x60_mc_pdata *pdata)
622 {
623         struct csrow_info *csrow;
624         u32 devtype;
625         u32 ctl;
626
627         get_total_mem(pdata);
628
629         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
630
631         csrow = &mci->csrows[0];
632         csrow->first_page = 0;
633         csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT;
634         csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
635         csrow->grain = 8;
636
637         csrow->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
638
639         devtype = (ctl >> 20) & 0x3;
640         switch (devtype) {
641         case 0x0:
642                 csrow->dtype = DEV_X32;
643                 break;
644         case 0x2:               /* could be X8 too, but no way to tell */
645                 csrow->dtype = DEV_X16;
646                 break;
647         case 0x3:
648                 csrow->dtype = DEV_X4;
649                 break;
650         default:
651                 csrow->dtype = DEV_UNKNOWN;
652                 break;
653         }
654
655         csrow->edac_mode = EDAC_SECDED;
656 }
657
658 static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev)
659 {
660         struct mem_ctl_info *mci;
661         struct mv64x60_mc_pdata *pdata;
662         struct resource *r;
663         u32 ctl;
664         int res = 0;
665
666         if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL))
667                 return -ENOMEM;
668
669         mci = edac_mc_alloc(sizeof(struct mv64x60_mc_pdata), 1, 1, edac_mc_idx);
670         if (!mci) {
671                 printk(KERN_ERR "%s: No memory for CPU err\n", __func__);
672                 devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
673                 return -ENOMEM;
674         }
675
676         pdata = mci->pvt_info;
677         mci->dev = &pdev->dev;
678         platform_set_drvdata(pdev, mci);
679         pdata->name = "mv64x60_mc_err";
680         pdata->irq = NO_IRQ;
681         mci->dev_name = pdev->dev.bus_id;
682         pdata->edac_idx = edac_mc_idx++;
683
684         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
685         if (!r) {
686                 printk(KERN_ERR "%s: Unable to get resource for "
687                        "MC err regs\n", __func__);
688                 res = -ENOENT;
689                 goto err;
690         }
691
692         if (!devm_request_mem_region(&pdev->dev,
693                                      r->start,
694                                      r->end - r->start + 1,
695                                      pdata->name)) {
696                 printk(KERN_ERR "%s: Error while requesting mem region\n",
697                        __func__);
698                 res = -EBUSY;
699                 goto err;
700         }
701
702         pdata->mc_vbase = devm_ioremap(&pdev->dev,
703                                        r->start,
704                                        r->end - r->start + 1);
705         if (!pdata->mc_vbase) {
706                 printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
707                 res = -ENOMEM;
708                 goto err;
709         }
710
711         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
712         if (!(ctl & MV64X60_SDRAM_ECC)) {
713                 /* Non-ECC RAM? */
714                 printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
715                 res = -ENODEV;
716                 goto err2;
717         }
718
719         debugf3("%s(): init mci\n", __func__);
720         mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
721         mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
722         mci->edac_cap = EDAC_FLAG_SECDED;
723         mci->mod_name = EDAC_MOD_STR;
724         mci->mod_ver = MV64x60_REVISION;
725         mci->ctl_name = mv64x60_ctl_name;
726
727         if (edac_op_state == EDAC_OPSTATE_POLL)
728                 mci->edac_check = mv64x60_mc_check;
729
730         mci->ctl_page_to_phys = NULL;
731
732         mci->scrub_mode = SCRUB_SW_SRC;
733
734         mv64x60_init_csrows(mci, pdata);
735
736         /* setup MC registers */
737         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
738         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
739         ctl = (ctl & 0xff00ffff) | 0x10000;
740         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl);
741
742         if (edac_mc_add_mc(mci)) {
743                 debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
744                 goto err;
745         }
746
747         if (edac_op_state == EDAC_OPSTATE_INT) {
748                 /* acquire interrupt that reports errors */
749                 pdata->irq = platform_get_irq(pdev, 0);
750                 res = devm_request_irq(&pdev->dev,
751                                        pdata->irq,
752                                        mv64x60_mc_isr,
753                                        IRQF_DISABLED,
754                                        "[EDAC] MC err",
755                                        mci);
756                 if (res < 0) {
757                         printk(KERN_ERR "%s: Unable to request irq %d for "
758                                "MV64x60 DRAM ERR\n", __func__, pdata->irq);
759                         res = -ENODEV;
760                         goto err2;
761                 }
762
763                 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n",
764                        pdata->irq);
765         }
766
767         /* get this far and it's successful */
768         debugf3("%s(): success\n", __func__);
769
770         return 0;
771
772 err2:
773         edac_mc_del_mc(&pdev->dev);
774 err:
775         devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
776         edac_mc_free(mci);
777         return res;
778 }
779
780 static int mv64x60_mc_err_remove(struct platform_device *pdev)
781 {
782         struct mem_ctl_info *mci = platform_get_drvdata(pdev);
783
784         debugf0("%s()\n", __func__);
785
786         edac_mc_del_mc(&pdev->dev);
787         edac_mc_free(mci);
788         return 0;
789 }
790
791 static struct platform_driver mv64x60_mc_err_driver = {
792         .probe = mv64x60_mc_err_probe,
793         .remove = mv64x60_mc_err_remove,
794         .driver = {
795                    .name = "mv64x60_mc_err",
796         }
797 };
798
799 static int __init mv64x60_edac_init(void)
800 {
801         int ret = 0;
802
803         printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n");
804         printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n");
805         /* make sure error reporting method is sane */
806         switch (edac_op_state) {
807         case EDAC_OPSTATE_POLL:
808         case EDAC_OPSTATE_INT:
809                 break;
810         default:
811                 edac_op_state = EDAC_OPSTATE_INT;
812                 break;
813         }
814
815         ret = platform_driver_register(&mv64x60_mc_err_driver);
816         if (ret)
817                 printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n");
818
819         ret = platform_driver_register(&mv64x60_cpu_err_driver);
820         if (ret)
821                 printk(KERN_WARNING EDAC_MOD_STR
822                         "CPU err failed to register\n");
823
824         ret = platform_driver_register(&mv64x60_sram_err_driver);
825         if (ret)
826                 printk(KERN_WARNING EDAC_MOD_STR
827                         "SRAM err failed to register\n");
828
829 #ifdef CONFIG_PCI
830         ret = platform_driver_register(&mv64x60_pci_err_driver);
831         if (ret)
832                 printk(KERN_WARNING EDAC_MOD_STR
833                         "PCI err failed to register\n");
834 #endif
835
836         return ret;
837 }
838 module_init(mv64x60_edac_init);
839
840 static void __exit mv64x60_edac_exit(void)
841 {
842 #ifdef CONFIG_PCI
843         platform_driver_unregister(&mv64x60_pci_err_driver);
844 #endif
845         platform_driver_unregister(&mv64x60_sram_err_driver);
846         platform_driver_unregister(&mv64x60_cpu_err_driver);
847         platform_driver_unregister(&mv64x60_mc_err_driver);
848 }
849 module_exit(mv64x60_edac_exit);
850
851 MODULE_LICENSE("GPL");
852 MODULE_AUTHOR("Montavista Software, Inc.");
853 module_param(edac_op_state, int, 0444);
854 MODULE_PARM_DESC(edac_op_state,
855                  "EDAC Error Reporting state: 0=Poll, 2=Interrupt");