2 * Freescale MPC85xx Memory Controller kernel module
4 * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc.
8 * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/interrupt.h>
17 #include <linux/ctype.h>
19 #include <linux/mod_devicetable.h>
20 #include <linux/edac.h>
21 #include <linux/smp.h>
22 #include <linux/gfp.h>
23 #include <linux/fsl/edac.h>
25 #include <linux/of_platform.h>
26 #include <linux/of_device.h>
27 #include <linux/of_address.h>
28 #include <linux/of_irq.h>
29 #include "edac_module.h"
30 #include "mpc85xx_edac.h"
31 #include "fsl_ddr_edac.h"
33 static int edac_dev_idx;
35 static int edac_pci_idx;
42 static u32 orig_pci_err_cap_dr;
43 static u32 orig_pci_err_en;
46 static u32 orig_l2_err_disable;
48 /**************************** PCI Err device ***************************/
51 static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
53 struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
56 err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
58 /* master aborts can happen during PCI config cycles */
59 if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
60 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
64 pr_err("PCI error(s) detected\n");
65 pr_err("PCI/X ERR_DR register: %#08x\n", err_detect);
67 pr_err("PCI/X ERR_ATTRIB register: %#08x\n",
68 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
69 pr_err("PCI/X ERR_ADDR register: %#08x\n",
70 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
71 pr_err("PCI/X ERR_EXT_ADDR register: %#08x\n",
72 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
73 pr_err("PCI/X ERR_DL register: %#08x\n",
74 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
75 pr_err("PCI/X ERR_DH register: %#08x\n",
76 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
78 /* clear error bits */
79 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
81 if (err_detect & PCI_EDE_PERR_MASK)
82 edac_pci_handle_pe(pci, pci->ctl_name);
84 if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK)
85 edac_pci_handle_npe(pci, pci->ctl_name);
88 static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
90 struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
91 u32 err_detect, err_cap_stat;
93 err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
94 err_cap_stat = in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR);
96 pr_err("PCIe error(s) detected\n");
97 pr_err("PCIe ERR_DR register: 0x%08x\n", err_detect);
98 pr_err("PCIe ERR_CAP_STAT register: 0x%08x\n", err_cap_stat);
99 pr_err("PCIe ERR_CAP_R0 register: 0x%08x\n",
100 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));
101 pr_err("PCIe ERR_CAP_R1 register: 0x%08x\n",
102 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));
103 pr_err("PCIe ERR_CAP_R2 register: 0x%08x\n",
104 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));
105 pr_err("PCIe ERR_CAP_R3 register: 0x%08x\n",
106 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));
108 /* clear error bits */
109 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
111 /* reset error capture */
112 out_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR, err_cap_stat | 0x1);
115 static int mpc85xx_pcie_find_capability(struct device_node *np)
117 struct pci_controller *hose;
122 hose = pci_find_hose_for_OF_device(np);
124 return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
127 static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
129 struct edac_pci_ctl_info *pci = dev_id;
130 struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
133 err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
139 mpc85xx_pcie_check(pci);
141 mpc85xx_pci_check(pci);
146 static int mpc85xx_pci_err_probe(struct platform_device *op)
148 struct edac_pci_ctl_info *pci;
149 struct mpc85xx_pci_pdata *pdata;
150 struct mpc85xx_edac_pci_plat_data *plat_data;
151 struct device_node *of_node;
155 if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
158 pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err");
162 /* make sure error reporting method is sane */
163 switch (edac_op_state) {
164 case EDAC_OPSTATE_POLL:
165 case EDAC_OPSTATE_INT:
168 edac_op_state = EDAC_OPSTATE_INT;
172 pdata = pci->pvt_info;
173 pdata->name = "mpc85xx_pci_err";
175 plat_data = op->dev.platform_data;
177 dev_err(&op->dev, "no platform data");
181 of_node = plat_data->of_node;
183 if (mpc85xx_pcie_find_capability(of_node) > 0)
184 pdata->is_pcie = true;
186 dev_set_drvdata(&op->dev, pci);
188 pci->mod_name = EDAC_MOD_STR;
189 pci->ctl_name = pdata->name;
190 pci->dev_name = dev_name(&op->dev);
192 if (edac_op_state == EDAC_OPSTATE_POLL) {
194 pci->edac_check = mpc85xx_pcie_check;
196 pci->edac_check = mpc85xx_pci_check;
199 pdata->edac_idx = edac_pci_idx++;
201 res = of_address_to_resource(of_node, 0, &r);
203 pr_err("%s: Unable to get resource for PCI err regs\n", __func__);
207 /* we only need the error registers */
210 if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
212 pr_err("%s: Error while requesting mem region\n", __func__);
217 pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
218 if (!pdata->pci_vbase) {
219 pr_err("%s: Unable to setup PCI err regs\n", __func__);
224 if (pdata->is_pcie) {
225 orig_pci_err_cap_dr =
226 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR);
227 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0);
229 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
230 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0);
232 orig_pci_err_cap_dr =
233 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
235 /* PCI master abort is expected during config cycles */
236 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
239 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
241 /* disable master abort reporting */
242 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
245 /* clear error bits */
246 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
248 /* reset error capture */
249 out_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR, 0x1);
251 if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
252 edac_dbg(3, "failed edac_pci_add_device()\n");
256 if (edac_op_state == EDAC_OPSTATE_INT) {
257 pdata->irq = irq_of_parse_and_map(of_node, 0);
258 res = devm_request_irq(&op->dev, pdata->irq,
261 "[EDAC] PCI err", pci);
263 pr_err("%s: Unable to request irq %d for MPC85xx PCI err\n",
264 __func__, pdata->irq);
265 irq_dispose_mapping(pdata->irq);
270 pr_info(EDAC_MOD_STR " acquired irq %d for PCI Err\n",
274 if (pdata->is_pcie) {
276 * Enable all PCIe error interrupt & error detect except invalid
277 * PEX_CONFIG_ADDR/PEX_CONFIG_DATA access interrupt generation
278 * enable bit and invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access
279 * detection enable bit. Because PCIe bus code to initialize and
280 * configure these PCIe devices on booting will use some invalid
281 * PEX_CONFIG_ADDR/PEX_CONFIG_DATA, edac driver prints the much
282 * notice information. So disable this detect to fix ugly print.
284 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0
285 & ~PEX_ERR_ICCAIE_EN_BIT);
286 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0
287 | PEX_ERR_ICCAD_DISR_BIT);
290 devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
291 edac_dbg(3, "success\n");
292 pr_info(EDAC_MOD_STR " PCI err registered\n");
297 edac_pci_del_device(&op->dev);
299 edac_pci_free_ctl_info(pci);
300 devres_release_group(&op->dev, mpc85xx_pci_err_probe);
304 static int mpc85xx_pci_err_remove(struct platform_device *op)
306 struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);
307 struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
311 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, orig_pci_err_cap_dr);
312 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);
314 edac_pci_del_device(&op->dev);
315 edac_pci_free_ctl_info(pci);
320 static const struct platform_device_id mpc85xx_pci_err_match[] = {
322 .name = "mpc85xx-pci-edac"
327 static struct platform_driver mpc85xx_pci_err_driver = {
328 .probe = mpc85xx_pci_err_probe,
329 .remove = mpc85xx_pci_err_remove,
330 .id_table = mpc85xx_pci_err_match,
332 .name = "mpc85xx_pci_err",
333 .suppress_bind_attrs = true,
336 #endif /* CONFIG_PCI */
338 /**************************** L2 Err device ***************************/
340 /************************ L2 SYSFS parts ***********************************/
342 static ssize_t mpc85xx_l2_inject_data_hi_show(struct edac_device_ctl_info
343 *edac_dev, char *data)
345 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
346 return sprintf(data, "0x%08x",
347 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI));
350 static ssize_t mpc85xx_l2_inject_data_lo_show(struct edac_device_ctl_info
351 *edac_dev, char *data)
353 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
354 return sprintf(data, "0x%08x",
355 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO));
358 static ssize_t mpc85xx_l2_inject_ctrl_show(struct edac_device_ctl_info
359 *edac_dev, char *data)
361 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
362 return sprintf(data, "0x%08x",
363 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL));
366 static ssize_t mpc85xx_l2_inject_data_hi_store(struct edac_device_ctl_info
367 *edac_dev, const char *data,
370 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
371 if (isdigit(*data)) {
372 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI,
373 simple_strtoul(data, NULL, 0));
379 static ssize_t mpc85xx_l2_inject_data_lo_store(struct edac_device_ctl_info
380 *edac_dev, const char *data,
383 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
384 if (isdigit(*data)) {
385 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO,
386 simple_strtoul(data, NULL, 0));
392 static ssize_t mpc85xx_l2_inject_ctrl_store(struct edac_device_ctl_info
393 *edac_dev, const char *data,
396 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
397 if (isdigit(*data)) {
398 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL,
399 simple_strtoul(data, NULL, 0));
405 static struct edac_dev_sysfs_attribute mpc85xx_l2_sysfs_attributes[] = {
408 .name = "inject_data_hi",
409 .mode = (S_IRUGO | S_IWUSR)
411 .show = mpc85xx_l2_inject_data_hi_show,
412 .store = mpc85xx_l2_inject_data_hi_store},
415 .name = "inject_data_lo",
416 .mode = (S_IRUGO | S_IWUSR)
418 .show = mpc85xx_l2_inject_data_lo_show,
419 .store = mpc85xx_l2_inject_data_lo_store},
422 .name = "inject_ctrl",
423 .mode = (S_IRUGO | S_IWUSR)
425 .show = mpc85xx_l2_inject_ctrl_show,
426 .store = mpc85xx_l2_inject_ctrl_store},
430 .attr = {.name = NULL}
434 static void mpc85xx_set_l2_sysfs_attributes(struct edac_device_ctl_info
437 edac_dev->sysfs_attributes = mpc85xx_l2_sysfs_attributes;
440 /***************************** L2 ops ***********************************/
442 static void mpc85xx_l2_check(struct edac_device_ctl_info *edac_dev)
444 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
447 err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);
449 if (!(err_detect & L2_EDE_MASK))
452 pr_err("ECC Error in CPU L2 cache\n");
453 pr_err("L2 Error Detect Register: 0x%08x\n", err_detect);
454 pr_err("L2 Error Capture Data High Register: 0x%08x\n",
455 in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATAHI));
456 pr_err("L2 Error Capture Data Lo Register: 0x%08x\n",
457 in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATALO));
458 pr_err("L2 Error Syndrome Register: 0x%08x\n",
459 in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTECC));
460 pr_err("L2 Error Attributes Capture Register: 0x%08x\n",
461 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRATTR));
462 pr_err("L2 Error Address Capture Register: 0x%08x\n",
463 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRADDR));
465 /* clear error detect register */
466 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, err_detect);
468 if (err_detect & L2_EDE_CE_MASK)
469 edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
471 if (err_detect & L2_EDE_UE_MASK)
472 edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
475 static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id)
477 struct edac_device_ctl_info *edac_dev = dev_id;
478 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
481 err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);
483 if (!(err_detect & L2_EDE_MASK))
486 mpc85xx_l2_check(edac_dev);
491 static int mpc85xx_l2_err_probe(struct platform_device *op)
493 struct edac_device_ctl_info *edac_dev;
494 struct mpc85xx_l2_pdata *pdata;
498 if (!devres_open_group(&op->dev, mpc85xx_l2_err_probe, GFP_KERNEL))
501 edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
502 "cpu", 1, "L", 1, 2, NULL, 0,
505 devres_release_group(&op->dev, mpc85xx_l2_err_probe);
509 pdata = edac_dev->pvt_info;
510 pdata->name = "mpc85xx_l2_err";
511 edac_dev->dev = &op->dev;
512 dev_set_drvdata(edac_dev->dev, edac_dev);
513 edac_dev->ctl_name = pdata->name;
514 edac_dev->dev_name = pdata->name;
516 res = of_address_to_resource(op->dev.of_node, 0, &r);
518 pr_err("%s: Unable to get resource for L2 err regs\n", __func__);
522 /* we only need the error registers */
525 if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
527 pr_err("%s: Error while requesting mem region\n", __func__);
532 pdata->l2_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
533 if (!pdata->l2_vbase) {
534 pr_err("%s: Unable to setup L2 err regs\n", __func__);
539 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, ~0);
541 orig_l2_err_disable = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS);
543 /* clear the err_dis */
544 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, 0);
546 edac_dev->mod_name = EDAC_MOD_STR;
548 if (edac_op_state == EDAC_OPSTATE_POLL)
549 edac_dev->edac_check = mpc85xx_l2_check;
551 mpc85xx_set_l2_sysfs_attributes(edac_dev);
553 pdata->edac_idx = edac_dev_idx++;
555 if (edac_device_add_device(edac_dev) > 0) {
556 edac_dbg(3, "failed edac_device_add_device()\n");
560 if (edac_op_state == EDAC_OPSTATE_INT) {
561 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
562 res = devm_request_irq(&op->dev, pdata->irq,
563 mpc85xx_l2_isr, IRQF_SHARED,
564 "[EDAC] L2 err", edac_dev);
566 pr_err("%s: Unable to request irq %d for MPC85xx L2 err\n",
567 __func__, pdata->irq);
568 irq_dispose_mapping(pdata->irq);
573 pr_info(EDAC_MOD_STR " acquired irq %d for L2 Err\n", pdata->irq);
575 edac_dev->op_state = OP_RUNNING_INTERRUPT;
577 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, L2_EIE_MASK);
580 devres_remove_group(&op->dev, mpc85xx_l2_err_probe);
582 edac_dbg(3, "success\n");
583 pr_info(EDAC_MOD_STR " L2 err registered\n");
588 edac_device_del_device(&op->dev);
590 devres_release_group(&op->dev, mpc85xx_l2_err_probe);
591 edac_device_free_ctl_info(edac_dev);
595 static int mpc85xx_l2_err_remove(struct platform_device *op)
597 struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev);
598 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
602 if (edac_op_state == EDAC_OPSTATE_INT) {
603 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0);
604 irq_dispose_mapping(pdata->irq);
607 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, orig_l2_err_disable);
608 edac_device_del_device(&op->dev);
609 edac_device_free_ctl_info(edac_dev);
613 static const struct of_device_id mpc85xx_l2_err_of_match[] = {
614 { .compatible = "fsl,mpc8536-l2-cache-controller", },
615 { .compatible = "fsl,mpc8540-l2-cache-controller", },
616 { .compatible = "fsl,mpc8541-l2-cache-controller", },
617 { .compatible = "fsl,mpc8544-l2-cache-controller", },
618 { .compatible = "fsl,mpc8548-l2-cache-controller", },
619 { .compatible = "fsl,mpc8555-l2-cache-controller", },
620 { .compatible = "fsl,mpc8560-l2-cache-controller", },
621 { .compatible = "fsl,mpc8568-l2-cache-controller", },
622 { .compatible = "fsl,mpc8569-l2-cache-controller", },
623 { .compatible = "fsl,mpc8572-l2-cache-controller", },
624 { .compatible = "fsl,p1020-l2-cache-controller", },
625 { .compatible = "fsl,p1021-l2-cache-controller", },
626 { .compatible = "fsl,p2020-l2-cache-controller", },
627 { .compatible = "fsl,t2080-l2-cache-controller", },
630 MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
632 static struct platform_driver mpc85xx_l2_err_driver = {
633 .probe = mpc85xx_l2_err_probe,
634 .remove = mpc85xx_l2_err_remove,
636 .name = "mpc85xx_l2_err",
637 .of_match_table = mpc85xx_l2_err_of_match,
641 static const struct of_device_id mpc85xx_mc_err_of_match[] = {
642 { .compatible = "fsl,mpc8536-memory-controller", },
643 { .compatible = "fsl,mpc8540-memory-controller", },
644 { .compatible = "fsl,mpc8541-memory-controller", },
645 { .compatible = "fsl,mpc8544-memory-controller", },
646 { .compatible = "fsl,mpc8548-memory-controller", },
647 { .compatible = "fsl,mpc8555-memory-controller", },
648 { .compatible = "fsl,mpc8560-memory-controller", },
649 { .compatible = "fsl,mpc8568-memory-controller", },
650 { .compatible = "fsl,mpc8569-memory-controller", },
651 { .compatible = "fsl,mpc8572-memory-controller", },
652 { .compatible = "fsl,mpc8349-memory-controller", },
653 { .compatible = "fsl,p1020-memory-controller", },
654 { .compatible = "fsl,p1021-memory-controller", },
655 { .compatible = "fsl,p2020-memory-controller", },
656 { .compatible = "fsl,qoriq-memory-controller", },
659 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
661 static struct platform_driver mpc85xx_mc_err_driver = {
662 .probe = fsl_mc_err_probe,
663 .remove = fsl_mc_err_remove,
665 .name = "mpc85xx_mc_err",
666 .of_match_table = mpc85xx_mc_err_of_match,
670 static struct platform_driver * const drivers[] = {
671 &mpc85xx_mc_err_driver,
672 &mpc85xx_l2_err_driver,
674 &mpc85xx_pci_err_driver,
678 static int __init mpc85xx_mc_init(void)
681 u32 __maybe_unused pvr = 0;
683 pr_info("Freescale(R) MPC85xx EDAC driver, (C) 2006 Montavista Software\n");
685 /* make sure error reporting method is sane */
686 switch (edac_op_state) {
687 case EDAC_OPSTATE_POLL:
688 case EDAC_OPSTATE_INT:
691 edac_op_state = EDAC_OPSTATE_INT;
695 res = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
697 pr_warn(EDAC_MOD_STR "drivers fail to register\n");
702 module_init(mpc85xx_mc_init);
704 static void __exit mpc85xx_mc_exit(void)
706 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
709 module_exit(mpc85xx_mc_exit);
711 MODULE_LICENSE("GPL");
712 MODULE_AUTHOR("Montavista Software, Inc.");
713 module_param(edac_op_state, int, 0444);
714 MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll, 2=Interrupt");