2 * Marvell MV64x60 Memory Controller kernel module for PPC platforms
4 * Author: Dave Jiang <djiang@mvista.com>
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
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/interrupt.h>
17 #include <linux/edac.h>
18 #include <linux/gfp.h>
20 #include "edac_core.h"
21 #include "edac_module.h"
22 #include "mv64x60_edac.h"
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
;
29 /*********************** PCI err device **********************************/
31 static void mv64x60_pci_check(struct edac_pci_ctl_info
*pci
)
33 struct mv64x60_pci_pdata
*pdata
= pci
->pvt_info
;
36 cause
= in_le32(pdata
->pci_vbase
+ MV64X60_PCI_ERROR_CAUSE
);
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
);
52 if (cause
& MV64X60_PCI_PE_MASK
)
53 edac_pci_handle_pe(pci
, pci
->ctl_name
);
55 if (!(cause
& MV64X60_PCI_PE_MASK
))
56 edac_pci_handle_npe(pci
, pci
->ctl_name
);
59 static irqreturn_t
mv64x60_pci_isr(int irq
, void *dev_id
)
61 struct edac_pci_ctl_info
*pci
= dev_id
;
62 struct mv64x60_pci_pdata
*pdata
= pci
->pvt_info
;
65 val
= in_le32(pdata
->pci_vbase
+ MV64X60_PCI_ERROR_CAUSE
);
69 mv64x60_pci_check(pci
);
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.
80 /* Erratum FEr PCI-#16: clear bit 0 of PCI SERRn Mask reg. */
81 static int __init
mv64x60_pci_fixup(struct platform_device
*pdev
)
84 void __iomem
*pci_serr
;
86 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
88 printk(KERN_ERR
"%s: Unable to get resource for "
89 "PCI err regs\n", __func__
);
93 pci_serr
= ioremap(r
->start
, resource_size(r
));
97 out_le32(pci_serr
, in_le32(pci_serr
) & ~0x1);
103 static int mv64x60_pci_err_probe(struct platform_device
*pdev
)
105 struct edac_pci_ctl_info
*pci
;
106 struct mv64x60_pci_pdata
*pdata
;
110 if (!devres_open_group(&pdev
->dev
, mv64x60_pci_err_probe
, GFP_KERNEL
))
113 pci
= edac_pci_alloc_ctl_info(sizeof(*pdata
), "mv64x60_pci_err");
117 pdata
= pci
->pvt_info
;
119 pdata
->pci_hose
= pdev
->id
;
120 pdata
->name
= "mpc85xx_pci_err";
121 platform_set_drvdata(pdev
, pci
);
122 pci
->dev
= &pdev
->dev
;
123 pci
->dev_name
= dev_name(&pdev
->dev
);
124 pci
->mod_name
= EDAC_MOD_STR
;
125 pci
->ctl_name
= pdata
->name
;
127 if (edac_op_state
== EDAC_OPSTATE_POLL
)
128 pci
->edac_check
= mv64x60_pci_check
;
130 pdata
->edac_idx
= edac_pci_idx
++;
132 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
134 printk(KERN_ERR
"%s: Unable to get resource for "
135 "PCI err regs\n", __func__
);
140 if (!devm_request_mem_region(&pdev
->dev
,
144 printk(KERN_ERR
"%s: Error while requesting mem region\n",
150 pdata
->pci_vbase
= devm_ioremap(&pdev
->dev
,
153 if (!pdata
->pci_vbase
) {
154 printk(KERN_ERR
"%s: Unable to setup PCI err regs\n", __func__
);
159 res
= mv64x60_pci_fixup(pdev
);
161 printk(KERN_ERR
"%s: PCI fixup failed\n", __func__
);
165 out_le32(pdata
->pci_vbase
+ MV64X60_PCI_ERROR_CAUSE
, 0);
166 out_le32(pdata
->pci_vbase
+ MV64X60_PCI_ERROR_MASK
, 0);
167 out_le32(pdata
->pci_vbase
+ MV64X60_PCI_ERROR_MASK
,
168 MV64X60_PCIx_ERR_MASK_VAL
);
170 if (edac_pci_add_device(pci
, pdata
->edac_idx
) > 0) {
171 edac_dbg(3, "failed edac_pci_add_device()\n");
175 if (edac_op_state
== EDAC_OPSTATE_INT
) {
176 pdata
->irq
= platform_get_irq(pdev
, 0);
177 res
= devm_request_irq(&pdev
->dev
,
184 printk(KERN_ERR
"%s: Unable to request irq %d for "
185 "MV64x60 PCI ERR\n", __func__
, pdata
->irq
);
189 printk(KERN_INFO EDAC_MOD_STR
" acquired irq %d for PCI Err\n",
193 devres_remove_group(&pdev
->dev
, mv64x60_pci_err_probe
);
195 /* get this far and it's successful */
196 edac_dbg(3, "success\n");
201 edac_pci_del_device(&pdev
->dev
);
203 edac_pci_free_ctl_info(pci
);
204 devres_release_group(&pdev
->dev
, mv64x60_pci_err_probe
);
208 static int mv64x60_pci_err_remove(struct platform_device
*pdev
)
210 struct edac_pci_ctl_info
*pci
= platform_get_drvdata(pdev
);
214 edac_pci_del_device(&pdev
->dev
);
216 edac_pci_free_ctl_info(pci
);
221 static struct platform_driver mv64x60_pci_err_driver
= {
222 .probe
= mv64x60_pci_err_probe
,
223 .remove
= mv64x60_pci_err_remove
,
225 .name
= "mv64x60_pci_err",
229 #endif /* CONFIG_PCI */
231 /*********************** SRAM err device **********************************/
232 static void mv64x60_sram_check(struct edac_device_ctl_info
*edac_dev
)
234 struct mv64x60_sram_pdata
*pdata
= edac_dev
->pvt_info
;
237 cause
= in_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_CAUSE
);
241 printk(KERN_ERR
"Error in internal SRAM\n");
242 printk(KERN_ERR
"Cause register: 0x%08x\n", cause
);
243 printk(KERN_ERR
"Address Low: 0x%08x\n",
244 in_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_ADDR_LO
));
245 printk(KERN_ERR
"Address High: 0x%08x\n",
246 in_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_ADDR_HI
));
247 printk(KERN_ERR
"Data Low: 0x%08x\n",
248 in_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_DATA_LO
));
249 printk(KERN_ERR
"Data High: 0x%08x\n",
250 in_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_DATA_HI
));
251 printk(KERN_ERR
"Parity: 0x%08x\n",
252 in_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_PARITY
));
253 out_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_CAUSE
, 0);
255 edac_device_handle_ue(edac_dev
, 0, 0, edac_dev
->ctl_name
);
258 static irqreturn_t
mv64x60_sram_isr(int irq
, void *dev_id
)
260 struct edac_device_ctl_info
*edac_dev
= dev_id
;
261 struct mv64x60_sram_pdata
*pdata
= edac_dev
->pvt_info
;
264 cause
= in_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_CAUSE
);
268 mv64x60_sram_check(edac_dev
);
273 static int mv64x60_sram_err_probe(struct platform_device
*pdev
)
275 struct edac_device_ctl_info
*edac_dev
;
276 struct mv64x60_sram_pdata
*pdata
;
280 if (!devres_open_group(&pdev
->dev
, mv64x60_sram_err_probe
, GFP_KERNEL
))
283 edac_dev
= edac_device_alloc_ctl_info(sizeof(*pdata
),
284 "sram", 1, NULL
, 0, 0, NULL
, 0,
287 devres_release_group(&pdev
->dev
, mv64x60_sram_err_probe
);
291 pdata
= edac_dev
->pvt_info
;
292 pdata
->name
= "mv64x60_sram_err";
293 edac_dev
->dev
= &pdev
->dev
;
294 platform_set_drvdata(pdev
, edac_dev
);
295 edac_dev
->dev_name
= dev_name(&pdev
->dev
);
297 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
299 printk(KERN_ERR
"%s: Unable to get resource for "
300 "SRAM err regs\n", __func__
);
305 if (!devm_request_mem_region(&pdev
->dev
,
309 printk(KERN_ERR
"%s: Error while request mem region\n",
315 pdata
->sram_vbase
= devm_ioremap(&pdev
->dev
,
318 if (!pdata
->sram_vbase
) {
319 printk(KERN_ERR
"%s: Unable to setup SRAM err regs\n",
325 /* setup SRAM err registers */
326 out_le32(pdata
->sram_vbase
+ MV64X60_SRAM_ERR_CAUSE
, 0);
328 edac_dev
->mod_name
= EDAC_MOD_STR
;
329 edac_dev
->ctl_name
= pdata
->name
;
331 if (edac_op_state
== EDAC_OPSTATE_POLL
)
332 edac_dev
->edac_check
= mv64x60_sram_check
;
334 pdata
->edac_idx
= edac_dev_idx
++;
336 if (edac_device_add_device(edac_dev
) > 0) {
337 edac_dbg(3, "failed edac_device_add_device()\n");
341 if (edac_op_state
== EDAC_OPSTATE_INT
) {
342 pdata
->irq
= platform_get_irq(pdev
, 0);
343 res
= devm_request_irq(&pdev
->dev
,
351 "%s: Unable to request irq %d for "
352 "MV64x60 SRAM ERR\n", __func__
, pdata
->irq
);
357 printk(KERN_INFO EDAC_MOD_STR
" acquired irq %d for SRAM Err\n",
361 devres_remove_group(&pdev
->dev
, mv64x60_sram_err_probe
);
363 /* get this far and it's successful */
364 edac_dbg(3, "success\n");
369 edac_device_del_device(&pdev
->dev
);
371 devres_release_group(&pdev
->dev
, mv64x60_sram_err_probe
);
372 edac_device_free_ctl_info(edac_dev
);
376 static int mv64x60_sram_err_remove(struct platform_device
*pdev
)
378 struct edac_device_ctl_info
*edac_dev
= platform_get_drvdata(pdev
);
382 edac_device_del_device(&pdev
->dev
);
383 edac_device_free_ctl_info(edac_dev
);
388 static struct platform_driver mv64x60_sram_err_driver
= {
389 .probe
= mv64x60_sram_err_probe
,
390 .remove
= mv64x60_sram_err_remove
,
392 .name
= "mv64x60_sram_err",
396 /*********************** CPU err device **********************************/
397 static void mv64x60_cpu_check(struct edac_device_ctl_info
*edac_dev
)
399 struct mv64x60_cpu_pdata
*pdata
= edac_dev
->pvt_info
;
402 cause
= in_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_CAUSE
) &
403 MV64x60_CPU_CAUSE_MASK
;
407 printk(KERN_ERR
"Error on CPU interface\n");
408 printk(KERN_ERR
"Cause register: 0x%08x\n", cause
);
409 printk(KERN_ERR
"Address Low: 0x%08x\n",
410 in_le32(pdata
->cpu_vbase
[0] + MV64x60_CPU_ERR_ADDR_LO
));
411 printk(KERN_ERR
"Address High: 0x%08x\n",
412 in_le32(pdata
->cpu_vbase
[0] + MV64x60_CPU_ERR_ADDR_HI
));
413 printk(KERN_ERR
"Data Low: 0x%08x\n",
414 in_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_DATA_LO
));
415 printk(KERN_ERR
"Data High: 0x%08x\n",
416 in_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_DATA_HI
));
417 printk(KERN_ERR
"Parity: 0x%08x\n",
418 in_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_PARITY
));
419 out_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_CAUSE
, 0);
421 edac_device_handle_ue(edac_dev
, 0, 0, edac_dev
->ctl_name
);
424 static irqreturn_t
mv64x60_cpu_isr(int irq
, void *dev_id
)
426 struct edac_device_ctl_info
*edac_dev
= dev_id
;
427 struct mv64x60_cpu_pdata
*pdata
= edac_dev
->pvt_info
;
430 cause
= in_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_CAUSE
) &
431 MV64x60_CPU_CAUSE_MASK
;
435 mv64x60_cpu_check(edac_dev
);
440 static int mv64x60_cpu_err_probe(struct platform_device
*pdev
)
442 struct edac_device_ctl_info
*edac_dev
;
444 struct mv64x60_cpu_pdata
*pdata
;
447 if (!devres_open_group(&pdev
->dev
, mv64x60_cpu_err_probe
, GFP_KERNEL
))
450 edac_dev
= edac_device_alloc_ctl_info(sizeof(*pdata
),
451 "cpu", 1, NULL
, 0, 0, NULL
, 0,
454 devres_release_group(&pdev
->dev
, mv64x60_cpu_err_probe
);
458 pdata
= edac_dev
->pvt_info
;
459 pdata
->name
= "mv64x60_cpu_err";
460 edac_dev
->dev
= &pdev
->dev
;
461 platform_set_drvdata(pdev
, edac_dev
);
462 edac_dev
->dev_name
= dev_name(&pdev
->dev
);
464 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
466 printk(KERN_ERR
"%s: Unable to get resource for "
467 "CPU err regs\n", __func__
);
472 if (!devm_request_mem_region(&pdev
->dev
,
476 printk(KERN_ERR
"%s: Error while requesting mem region\n",
482 pdata
->cpu_vbase
[0] = devm_ioremap(&pdev
->dev
,
485 if (!pdata
->cpu_vbase
[0]) {
486 printk(KERN_ERR
"%s: Unable to setup CPU err regs\n", __func__
);
491 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 1);
493 printk(KERN_ERR
"%s: Unable to get resource for "
494 "CPU err regs\n", __func__
);
499 if (!devm_request_mem_region(&pdev
->dev
,
503 printk(KERN_ERR
"%s: Error while requesting mem region\n",
509 pdata
->cpu_vbase
[1] = devm_ioremap(&pdev
->dev
,
512 if (!pdata
->cpu_vbase
[1]) {
513 printk(KERN_ERR
"%s: Unable to setup CPU err regs\n", __func__
);
518 /* setup CPU err registers */
519 out_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_CAUSE
, 0);
520 out_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_MASK
, 0);
521 out_le32(pdata
->cpu_vbase
[1] + MV64x60_CPU_ERR_MASK
, 0x000000ff);
523 edac_dev
->mod_name
= EDAC_MOD_STR
;
524 edac_dev
->ctl_name
= pdata
->name
;
525 if (edac_op_state
== EDAC_OPSTATE_POLL
)
526 edac_dev
->edac_check
= mv64x60_cpu_check
;
528 pdata
->edac_idx
= edac_dev_idx
++;
530 if (edac_device_add_device(edac_dev
) > 0) {
531 edac_dbg(3, "failed edac_device_add_device()\n");
535 if (edac_op_state
== EDAC_OPSTATE_INT
) {
536 pdata
->irq
= platform_get_irq(pdev
, 0);
537 res
= devm_request_irq(&pdev
->dev
,
545 "%s: Unable to request irq %d for MV64x60 "
546 "CPU ERR\n", __func__
, pdata
->irq
);
551 printk(KERN_INFO EDAC_MOD_STR
552 " acquired irq %d for CPU Err\n", pdata
->irq
);
555 devres_remove_group(&pdev
->dev
, mv64x60_cpu_err_probe
);
557 /* get this far and it's successful */
558 edac_dbg(3, "success\n");
563 edac_device_del_device(&pdev
->dev
);
565 devres_release_group(&pdev
->dev
, mv64x60_cpu_err_probe
);
566 edac_device_free_ctl_info(edac_dev
);
570 static int mv64x60_cpu_err_remove(struct platform_device
*pdev
)
572 struct edac_device_ctl_info
*edac_dev
= platform_get_drvdata(pdev
);
576 edac_device_del_device(&pdev
->dev
);
577 edac_device_free_ctl_info(edac_dev
);
581 static struct platform_driver mv64x60_cpu_err_driver
= {
582 .probe
= mv64x60_cpu_err_probe
,
583 .remove
= mv64x60_cpu_err_remove
,
585 .name
= "mv64x60_cpu_err",
589 /*********************** DRAM err device **********************************/
591 static void mv64x60_mc_check(struct mem_ctl_info
*mci
)
593 struct mv64x60_mc_pdata
*pdata
= mci
->pvt_info
;
600 reg
= in_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ADDR
);
604 err_addr
= reg
& ~0x3;
605 sdram_ecc
= in_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ECC_RCVD
);
606 comp_ecc
= in_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ECC_CALC
);
607 syndrome
= sdram_ecc
^ comp_ecc
;
609 /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */
611 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED
, mci
, 1,
612 err_addr
>> PAGE_SHIFT
,
613 err_addr
& PAGE_MASK
, syndrome
,
616 else /* 2 bit error, UE */
617 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED
, mci
, 1,
618 err_addr
>> PAGE_SHIFT
,
619 err_addr
& PAGE_MASK
, 0,
623 /* clear the error */
624 out_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ADDR
, 0);
627 static irqreturn_t
mv64x60_mc_isr(int irq
, void *dev_id
)
629 struct mem_ctl_info
*mci
= dev_id
;
630 struct mv64x60_mc_pdata
*pdata
= mci
->pvt_info
;
633 reg
= in_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ADDR
);
637 /* writing 0's to the ECC err addr in check function clears irq */
638 mv64x60_mc_check(mci
);
643 static void get_total_mem(struct mv64x60_mc_pdata
*pdata
)
645 struct device_node
*np
= NULL
;
646 const unsigned int *reg
;
648 np
= of_find_node_by_type(NULL
, "memory");
652 reg
= of_get_property(np
, "reg", NULL
);
654 pdata
->total_mem
= reg
[1];
657 static void mv64x60_init_csrows(struct mem_ctl_info
*mci
,
658 struct mv64x60_mc_pdata
*pdata
)
660 struct csrow_info
*csrow
;
661 struct dimm_info
*dimm
;
666 get_total_mem(pdata
);
668 ctl
= in_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_CONFIG
);
670 csrow
= mci
->csrows
[0];
671 dimm
= csrow
->channels
[0]->dimm
;
673 dimm
->nr_pages
= pdata
->total_mem
>> PAGE_SHIFT
;
676 dimm
->mtype
= (ctl
& MV64X60_SDRAM_REGISTERED
) ? MEM_RDDR
: MEM_DDR
;
678 devtype
= (ctl
>> 20) & 0x3;
681 dimm
->dtype
= DEV_X32
;
683 case 0x2: /* could be X8 too, but no way to tell */
684 dimm
->dtype
= DEV_X16
;
687 dimm
->dtype
= DEV_X4
;
690 dimm
->dtype
= DEV_UNKNOWN
;
694 dimm
->edac_mode
= EDAC_SECDED
;
697 static int mv64x60_mc_err_probe(struct platform_device
*pdev
)
699 struct mem_ctl_info
*mci
;
700 struct edac_mc_layer layers
[2];
701 struct mv64x60_mc_pdata
*pdata
;
706 if (!devres_open_group(&pdev
->dev
, mv64x60_mc_err_probe
, GFP_KERNEL
))
709 layers
[0].type
= EDAC_MC_LAYER_CHIP_SELECT
;
711 layers
[0].is_virt_csrow
= true;
712 layers
[1].type
= EDAC_MC_LAYER_CHANNEL
;
714 layers
[1].is_virt_csrow
= false;
715 mci
= edac_mc_alloc(edac_mc_idx
, ARRAY_SIZE(layers
), layers
,
716 sizeof(struct mv64x60_mc_pdata
));
718 printk(KERN_ERR
"%s: No memory for CPU err\n", __func__
);
719 devres_release_group(&pdev
->dev
, mv64x60_mc_err_probe
);
723 pdata
= mci
->pvt_info
;
724 mci
->pdev
= &pdev
->dev
;
725 platform_set_drvdata(pdev
, mci
);
726 pdata
->name
= "mv64x60_mc_err";
727 mci
->dev_name
= dev_name(&pdev
->dev
);
728 pdata
->edac_idx
= edac_mc_idx
++;
730 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
732 printk(KERN_ERR
"%s: Unable to get resource for "
733 "MC err regs\n", __func__
);
738 if (!devm_request_mem_region(&pdev
->dev
,
742 printk(KERN_ERR
"%s: Error while requesting mem region\n",
748 pdata
->mc_vbase
= devm_ioremap(&pdev
->dev
,
751 if (!pdata
->mc_vbase
) {
752 printk(KERN_ERR
"%s: Unable to setup MC err regs\n", __func__
);
757 ctl
= in_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_CONFIG
);
758 if (!(ctl
& MV64X60_SDRAM_ECC
)) {
760 printk(KERN_WARNING
"%s: No ECC DIMMs discovered\n", __func__
);
765 edac_dbg(3, "init mci\n");
766 mci
->mtype_cap
= MEM_FLAG_RDDR
| MEM_FLAG_DDR
;
767 mci
->edac_ctl_cap
= EDAC_FLAG_NONE
| EDAC_FLAG_SECDED
;
768 mci
->edac_cap
= EDAC_FLAG_SECDED
;
769 mci
->mod_name
= EDAC_MOD_STR
;
770 mci
->mod_ver
= MV64x60_REVISION
;
771 mci
->ctl_name
= mv64x60_ctl_name
;
773 if (edac_op_state
== EDAC_OPSTATE_POLL
)
774 mci
->edac_check
= mv64x60_mc_check
;
776 mci
->ctl_page_to_phys
= NULL
;
778 mci
->scrub_mode
= SCRUB_SW_SRC
;
780 mv64x60_init_csrows(mci
, pdata
);
782 /* setup MC registers */
783 out_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ADDR
, 0);
784 ctl
= in_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ECC_CNTL
);
785 ctl
= (ctl
& 0xff00ffff) | 0x10000;
786 out_le32(pdata
->mc_vbase
+ MV64X60_SDRAM_ERR_ECC_CNTL
, ctl
);
788 res
= edac_mc_add_mc(mci
);
790 edac_dbg(3, "failed edac_mc_add_mc()\n");
794 if (edac_op_state
== EDAC_OPSTATE_INT
) {
795 /* acquire interrupt that reports errors */
796 pdata
->irq
= platform_get_irq(pdev
, 0);
797 res
= devm_request_irq(&pdev
->dev
,
804 printk(KERN_ERR
"%s: Unable to request irq %d for "
805 "MV64x60 DRAM ERR\n", __func__
, pdata
->irq
);
810 printk(KERN_INFO EDAC_MOD_STR
" acquired irq %d for MC Err\n",
814 /* get this far and it's successful */
815 edac_dbg(3, "success\n");
820 edac_mc_del_mc(&pdev
->dev
);
822 devres_release_group(&pdev
->dev
, mv64x60_mc_err_probe
);
827 static int mv64x60_mc_err_remove(struct platform_device
*pdev
)
829 struct mem_ctl_info
*mci
= platform_get_drvdata(pdev
);
833 edac_mc_del_mc(&pdev
->dev
);
838 static struct platform_driver mv64x60_mc_err_driver
= {
839 .probe
= mv64x60_mc_err_probe
,
840 .remove
= mv64x60_mc_err_remove
,
842 .name
= "mv64x60_mc_err",
846 static struct platform_driver
* const drivers
[] = {
847 &mv64x60_mc_err_driver
,
848 &mv64x60_cpu_err_driver
,
849 &mv64x60_sram_err_driver
,
851 &mv64x60_pci_err_driver
,
855 static int __init
mv64x60_edac_init(void)
859 printk(KERN_INFO
"Marvell MV64x60 EDAC driver " MV64x60_REVISION
"\n");
860 printk(KERN_INFO
"\t(C) 2006-2007 MontaVista Software\n");
861 /* make sure error reporting method is sane */
862 switch (edac_op_state
) {
863 case EDAC_OPSTATE_POLL
:
864 case EDAC_OPSTATE_INT
:
867 edac_op_state
= EDAC_OPSTATE_INT
;
871 return platform_register_drivers(drivers
, ARRAY_SIZE(drivers
));
873 module_init(mv64x60_edac_init
);
875 static void __exit
mv64x60_edac_exit(void)
877 platform_unregister_drivers(drivers
, ARRAY_SIZE(drivers
));
879 module_exit(mv64x60_edac_exit
);
881 MODULE_LICENSE("GPL");
882 MODULE_AUTHOR("Montavista Software, Inc.");
883 module_param(edac_op_state
, int, 0444);
884 MODULE_PARM_DESC(edac_op_state
,
885 "EDAC Error Reporting state: 0=Poll, 2=Interrupt");