Merge branch 'acpi-ec'
[linux-drm-fsl-dcu.git] / 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/interrupt.h>
16 #include <linux/io.h>
17 #include <linux/edac.h>
18 #include <linux/gfp.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, resource_size(r));
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 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                                      resource_size(r),
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                                         resource_size(r));
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                 edac_dbg(3, "failed edac_pci_add_device()\n");
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                                        0,
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         edac_dbg(3, "success\n");
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         edac_dbg(0, "\n");
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 = 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 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                                      resource_size(r),
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                                          resource_size(r));
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                 edac_dbg(3, "failed edac_device_add_device()\n");
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                                        0,
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         edac_dbg(3, "success\n");
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         edac_dbg(0, "\n");
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 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                                      resource_size(r),
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                                            resource_size(r));
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                                      resource_size(r),
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                                            resource_size(r));
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                 edac_dbg(3, "failed edac_device_add_device()\n");
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                                        0,
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         edac_dbg(3, "success\n");
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         edac_dbg(0, "\n");
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_error(HW_EVENT_ERR_CORRECTED, mci, 1,
615                                      err_addr >> PAGE_SHIFT,
616                                      err_addr & PAGE_MASK, syndrome,
617                                      0, 0, -1,
618                                      mci->ctl_name, "");
619         else    /* 2 bit error, UE */
620                 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
621                                      err_addr >> PAGE_SHIFT,
622                                      err_addr & PAGE_MASK, 0,
623                                      0, 0, -1,
624                                      mci->ctl_name, "");
625
626         /* clear the error */
627         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
628 }
629
630 static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
631 {
632         struct mem_ctl_info *mci = dev_id;
633         struct mv64x60_mc_pdata *pdata = mci->pvt_info;
634         u32 reg;
635
636         reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
637         if (!reg)
638                 return IRQ_NONE;
639
640         /* writing 0's to the ECC err addr in check function clears irq */
641         mv64x60_mc_check(mci);
642
643         return IRQ_HANDLED;
644 }
645
646 static void get_total_mem(struct mv64x60_mc_pdata *pdata)
647 {
648         struct device_node *np = NULL;
649         const unsigned int *reg;
650
651         np = of_find_node_by_type(NULL, "memory");
652         if (!np)
653                 return;
654
655         reg = of_get_property(np, "reg", NULL);
656
657         pdata->total_mem = reg[1];
658 }
659
660 static void mv64x60_init_csrows(struct mem_ctl_info *mci,
661                                 struct mv64x60_mc_pdata *pdata)
662 {
663         struct csrow_info *csrow;
664         struct dimm_info *dimm;
665
666         u32 devtype;
667         u32 ctl;
668
669         get_total_mem(pdata);
670
671         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
672
673         csrow = mci->csrows[0];
674         dimm = csrow->channels[0]->dimm;
675
676         dimm->nr_pages = pdata->total_mem >> PAGE_SHIFT;
677         dimm->grain = 8;
678
679         dimm->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
680
681         devtype = (ctl >> 20) & 0x3;
682         switch (devtype) {
683         case 0x0:
684                 dimm->dtype = DEV_X32;
685                 break;
686         case 0x2:               /* could be X8 too, but no way to tell */
687                 dimm->dtype = DEV_X16;
688                 break;
689         case 0x3:
690                 dimm->dtype = DEV_X4;
691                 break;
692         default:
693                 dimm->dtype = DEV_UNKNOWN;
694                 break;
695         }
696
697         dimm->edac_mode = EDAC_SECDED;
698 }
699
700 static int mv64x60_mc_err_probe(struct platform_device *pdev)
701 {
702         struct mem_ctl_info *mci;
703         struct edac_mc_layer layers[2];
704         struct mv64x60_mc_pdata *pdata;
705         struct resource *r;
706         u32 ctl;
707         int res = 0;
708
709         if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL))
710                 return -ENOMEM;
711
712         layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
713         layers[0].size = 1;
714         layers[0].is_virt_csrow = true;
715         layers[1].type = EDAC_MC_LAYER_CHANNEL;
716         layers[1].size = 1;
717         layers[1].is_virt_csrow = false;
718         mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers,
719                             sizeof(struct mv64x60_mc_pdata));
720         if (!mci) {
721                 printk(KERN_ERR "%s: No memory for CPU err\n", __func__);
722                 devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
723                 return -ENOMEM;
724         }
725
726         pdata = mci->pvt_info;
727         mci->pdev = &pdev->dev;
728         platform_set_drvdata(pdev, mci);
729         pdata->name = "mv64x60_mc_err";
730         pdata->irq = NO_IRQ;
731         mci->dev_name = dev_name(&pdev->dev);
732         pdata->edac_idx = edac_mc_idx++;
733
734         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
735         if (!r) {
736                 printk(KERN_ERR "%s: Unable to get resource for "
737                        "MC err regs\n", __func__);
738                 res = -ENOENT;
739                 goto err;
740         }
741
742         if (!devm_request_mem_region(&pdev->dev,
743                                      r->start,
744                                      resource_size(r),
745                                      pdata->name)) {
746                 printk(KERN_ERR "%s: Error while requesting mem region\n",
747                        __func__);
748                 res = -EBUSY;
749                 goto err;
750         }
751
752         pdata->mc_vbase = devm_ioremap(&pdev->dev,
753                                        r->start,
754                                        resource_size(r));
755         if (!pdata->mc_vbase) {
756                 printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
757                 res = -ENOMEM;
758                 goto err;
759         }
760
761         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
762         if (!(ctl & MV64X60_SDRAM_ECC)) {
763                 /* Non-ECC RAM? */
764                 printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
765                 res = -ENODEV;
766                 goto err2;
767         }
768
769         edac_dbg(3, "init mci\n");
770         mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
771         mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
772         mci->edac_cap = EDAC_FLAG_SECDED;
773         mci->mod_name = EDAC_MOD_STR;
774         mci->mod_ver = MV64x60_REVISION;
775         mci->ctl_name = mv64x60_ctl_name;
776
777         if (edac_op_state == EDAC_OPSTATE_POLL)
778                 mci->edac_check = mv64x60_mc_check;
779
780         mci->ctl_page_to_phys = NULL;
781
782         mci->scrub_mode = SCRUB_SW_SRC;
783
784         mv64x60_init_csrows(mci, pdata);
785
786         /* setup MC registers */
787         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
788         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
789         ctl = (ctl & 0xff00ffff) | 0x10000;
790         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl);
791
792         res = edac_mc_add_mc(mci);
793         if (res) {
794                 edac_dbg(3, "failed edac_mc_add_mc()\n");
795                 goto err;
796         }
797
798         if (edac_op_state == EDAC_OPSTATE_INT) {
799                 /* acquire interrupt that reports errors */
800                 pdata->irq = platform_get_irq(pdev, 0);
801                 res = devm_request_irq(&pdev->dev,
802                                        pdata->irq,
803                                        mv64x60_mc_isr,
804                                        0,
805                                        "[EDAC] MC err",
806                                        mci);
807                 if (res < 0) {
808                         printk(KERN_ERR "%s: Unable to request irq %d for "
809                                "MV64x60 DRAM ERR\n", __func__, pdata->irq);
810                         res = -ENODEV;
811                         goto err2;
812                 }
813
814                 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n",
815                        pdata->irq);
816         }
817
818         /* get this far and it's successful */
819         edac_dbg(3, "success\n");
820
821         return 0;
822
823 err2:
824         edac_mc_del_mc(&pdev->dev);
825 err:
826         devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
827         edac_mc_free(mci);
828         return res;
829 }
830
831 static int mv64x60_mc_err_remove(struct platform_device *pdev)
832 {
833         struct mem_ctl_info *mci = platform_get_drvdata(pdev);
834
835         edac_dbg(0, "\n");
836
837         edac_mc_del_mc(&pdev->dev);
838         edac_mc_free(mci);
839         return 0;
840 }
841
842 static struct platform_driver mv64x60_mc_err_driver = {
843         .probe = mv64x60_mc_err_probe,
844         .remove = mv64x60_mc_err_remove,
845         .driver = {
846                    .name = "mv64x60_mc_err",
847         }
848 };
849
850 static int __init mv64x60_edac_init(void)
851 {
852         int ret = 0;
853
854         printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n");
855         printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n");
856         /* make sure error reporting method is sane */
857         switch (edac_op_state) {
858         case EDAC_OPSTATE_POLL:
859         case EDAC_OPSTATE_INT:
860                 break;
861         default:
862                 edac_op_state = EDAC_OPSTATE_INT;
863                 break;
864         }
865
866         ret = platform_driver_register(&mv64x60_mc_err_driver);
867         if (ret)
868                 printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n");
869
870         ret = platform_driver_register(&mv64x60_cpu_err_driver);
871         if (ret)
872                 printk(KERN_WARNING EDAC_MOD_STR
873                         "CPU err failed to register\n");
874
875         ret = platform_driver_register(&mv64x60_sram_err_driver);
876         if (ret)
877                 printk(KERN_WARNING EDAC_MOD_STR
878                         "SRAM err failed to register\n");
879
880 #ifdef CONFIG_PCI
881         ret = platform_driver_register(&mv64x60_pci_err_driver);
882         if (ret)
883                 printk(KERN_WARNING EDAC_MOD_STR
884                         "PCI err failed to register\n");
885 #endif
886
887         return ret;
888 }
889 module_init(mv64x60_edac_init);
890
891 static void __exit mv64x60_edac_exit(void)
892 {
893 #ifdef CONFIG_PCI
894         platform_driver_unregister(&mv64x60_pci_err_driver);
895 #endif
896         platform_driver_unregister(&mv64x60_sram_err_driver);
897         platform_driver_unregister(&mv64x60_cpu_err_driver);
898         platform_driver_unregister(&mv64x60_mc_err_driver);
899 }
900 module_exit(mv64x60_edac_exit);
901
902 MODULE_LICENSE("GPL");
903 MODULE_AUTHOR("Montavista Software, Inc.");
904 module_param(edac_op_state, int, 0444);
905 MODULE_PARM_DESC(edac_op_state,
906                  "EDAC Error Reporting state: 0=Poll, 2=Interrupt");