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