brintos

brintos / linux-shallow public Read only

0
0
Text · 19.4 KiB · d0266cb Raw
712 lines · c
1/*2 * Freescale MPC85xx Memory Controller kernel module3 *4 * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc.5 *6 * Author: Dave Jiang <djiang@mvista.com>7 *8 * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under9 * the terms of the GNU General Public License version 2. This program10 * is licensed "as is" without any warranty of any kind, whether express11 * or implied.12 *13 */14#include <linux/module.h>15#include <linux/init.h>16#include <linux/interrupt.h>17#include <linux/ctype.h>18#include <linux/io.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>24 25#include <linux/of.h>26#include <linux/of_address.h>27#include <linux/of_irq.h>28#include "edac_module.h"29#include "mpc85xx_edac.h"30#include "fsl_ddr_edac.h"31 32static int edac_dev_idx;33#ifdef CONFIG_PCI34static int edac_pci_idx;35#endif36 37/*38 * PCI Err defines39 */40#ifdef CONFIG_PCI41static u32 orig_pci_err_cap_dr;42static u32 orig_pci_err_en;43#endif44 45static u32 orig_l2_err_disable;46 47/**************************** PCI Err device ***************************/48#ifdef CONFIG_PCI49 50static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)51{52	struct mpc85xx_pci_pdata *pdata = pci->pvt_info;53	u32 err_detect;54 55	err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);56 57	/* master aborts can happen during PCI config cycles */58	if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {59		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);60		return;61	}62 63	pr_err("PCI error(s) detected\n");64	pr_err("PCI/X ERR_DR register: %#08x\n", err_detect);65 66	pr_err("PCI/X ERR_ATTRIB register: %#08x\n",67	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));68	pr_err("PCI/X ERR_ADDR register: %#08x\n",69	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));70	pr_err("PCI/X ERR_EXT_ADDR register: %#08x\n",71	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));72	pr_err("PCI/X ERR_DL register: %#08x\n",73	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));74	pr_err("PCI/X ERR_DH register: %#08x\n",75	       in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));76 77	/* clear error bits */78	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);79 80	if (err_detect & PCI_EDE_PERR_MASK)81		edac_pci_handle_pe(pci, pci->ctl_name);82 83	if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK)84		edac_pci_handle_npe(pci, pci->ctl_name);85}86 87static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)88{89	struct mpc85xx_pci_pdata *pdata = pci->pvt_info;90	u32 err_detect, err_cap_stat;91 92	err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);93	err_cap_stat = in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR);94 95	pr_err("PCIe error(s) detected\n");96	pr_err("PCIe ERR_DR register: 0x%08x\n", err_detect);97	pr_err("PCIe ERR_CAP_STAT register: 0x%08x\n", err_cap_stat);98	pr_err("PCIe ERR_CAP_R0 register: 0x%08x\n",99			in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));100	pr_err("PCIe ERR_CAP_R1 register: 0x%08x\n",101			in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));102	pr_err("PCIe ERR_CAP_R2 register: 0x%08x\n",103			in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));104	pr_err("PCIe ERR_CAP_R3 register: 0x%08x\n",105			in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));106 107	/* clear error bits */108	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);109 110	/* reset error capture */111	out_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR, err_cap_stat | 0x1);112}113 114static int mpc85xx_pcie_find_capability(struct device_node *np)115{116	struct pci_controller *hose;117 118	if (!np)119		return -EINVAL;120 121	hose = pci_find_hose_for_OF_device(np);122 123	return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);124}125 126static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)127{128	struct edac_pci_ctl_info *pci = dev_id;129	struct mpc85xx_pci_pdata *pdata = pci->pvt_info;130	u32 err_detect;131 132	err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);133 134	if (!err_detect)135		return IRQ_NONE;136 137	if (pdata->is_pcie)138		mpc85xx_pcie_check(pci);139	else140		mpc85xx_pci_check(pci);141 142	return IRQ_HANDLED;143}144 145static int mpc85xx_pci_err_probe(struct platform_device *op)146{147	struct edac_pci_ctl_info *pci;148	struct mpc85xx_pci_pdata *pdata;149	struct mpc85xx_edac_pci_plat_data *plat_data;150	struct device_node *of_node;151	struct resource r;152	int res = 0;153 154	if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))155		return -ENOMEM;156 157	pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err");158	if (!pci)159		return -ENOMEM;160 161	/* make sure error reporting method is sane */162	switch (edac_op_state) {163	case EDAC_OPSTATE_POLL:164	case EDAC_OPSTATE_INT:165		break;166	default:167		edac_op_state = EDAC_OPSTATE_INT;168		break;169	}170 171	pdata = pci->pvt_info;172	pdata->name = "mpc85xx_pci_err";173 174	plat_data = op->dev.platform_data;175	if (!plat_data) {176		dev_err(&op->dev, "no platform data");177		res = -ENXIO;178		goto err;179	}180	of_node = plat_data->of_node;181 182	if (mpc85xx_pcie_find_capability(of_node) > 0)183		pdata->is_pcie = true;184 185	dev_set_drvdata(&op->dev, pci);186	pci->dev = &op->dev;187	pci->mod_name = EDAC_MOD_STR;188	pci->ctl_name = pdata->name;189	pci->dev_name = dev_name(&op->dev);190 191	if (edac_op_state == EDAC_OPSTATE_POLL) {192		if (pdata->is_pcie)193			pci->edac_check = mpc85xx_pcie_check;194		else195			pci->edac_check = mpc85xx_pci_check;196	}197 198	pdata->edac_idx = edac_pci_idx++;199 200	res = of_address_to_resource(of_node, 0, &r);201	if (res) {202		pr_err("%s: Unable to get resource for PCI err regs\n", __func__);203		goto err;204	}205 206	/* we only need the error registers */207	r.start += 0xe00;208 209	if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),210					pdata->name)) {211		pr_err("%s: Error while requesting mem region\n", __func__);212		res = -EBUSY;213		goto err;214	}215 216	pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));217	if (!pdata->pci_vbase) {218		pr_err("%s: Unable to setup PCI err regs\n", __func__);219		res = -ENOMEM;220		goto err;221	}222 223	if (pdata->is_pcie) {224		orig_pci_err_cap_dr =225		    in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR);226		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0);227		orig_pci_err_en =228		    in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);229		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0);230	} else {231		orig_pci_err_cap_dr =232		    in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);233 234		/* PCI master abort is expected during config cycles */235		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);236 237		orig_pci_err_en =238		    in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);239 240		/* disable master abort reporting */241		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);242	}243 244	/* clear error bits */245	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);246 247	/* reset error capture */248	out_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR, 0x1);249 250	if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {251		edac_dbg(3, "failed edac_pci_add_device()\n");252		goto err;253	}254 255	if (edac_op_state == EDAC_OPSTATE_INT) {256		pdata->irq = irq_of_parse_and_map(of_node, 0);257		res = devm_request_irq(&op->dev, pdata->irq,258				       mpc85xx_pci_isr,259				       IRQF_SHARED,260				       "[EDAC] PCI err", pci);261		if (res < 0) {262			pr_err("%s: Unable to request irq %d for MPC85xx PCI err\n",263				__func__, pdata->irq);264			irq_dispose_mapping(pdata->irq);265			res = -ENODEV;266			goto err2;267		}268 269		pr_info(EDAC_MOD_STR " acquired irq %d for PCI Err\n",270		       pdata->irq);271	}272 273	if (pdata->is_pcie) {274		/*275		 * Enable all PCIe error interrupt & error detect except invalid276		 * PEX_CONFIG_ADDR/PEX_CONFIG_DATA access interrupt generation277		 * enable bit and invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access278		 * detection enable bit. Because PCIe bus code to initialize and279		 * configure these PCIe devices on booting will use some invalid280		 * PEX_CONFIG_ADDR/PEX_CONFIG_DATA, edac driver prints the much281		 * notice information. So disable this detect to fix ugly print.282		 */283		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0284			 & ~PEX_ERR_ICCAIE_EN_BIT);285		out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0286			 | PEX_ERR_ICCAD_DISR_BIT);287	}288 289	devres_remove_group(&op->dev, mpc85xx_pci_err_probe);290	edac_dbg(3, "success\n");291	pr_info(EDAC_MOD_STR " PCI err registered\n");292 293	return 0;294 295err2:296	edac_pci_del_device(&op->dev);297err:298	edac_pci_free_ctl_info(pci);299	devres_release_group(&op->dev, mpc85xx_pci_err_probe);300	return res;301}302 303static void mpc85xx_pci_err_remove(struct platform_device *op)304{305	struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);306	struct mpc85xx_pci_pdata *pdata = pci->pvt_info;307 308	edac_dbg(0, "\n");309 310	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, orig_pci_err_cap_dr);311	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);312 313	edac_pci_del_device(&op->dev);314	edac_pci_free_ctl_info(pci);315}316 317static const struct platform_device_id mpc85xx_pci_err_match[] = {318	{319		.name = "mpc85xx-pci-edac"320	},321	{}322};323 324static struct platform_driver mpc85xx_pci_err_driver = {325	.probe = mpc85xx_pci_err_probe,326	.remove_new = mpc85xx_pci_err_remove,327	.id_table = mpc85xx_pci_err_match,328	.driver = {329		.name = "mpc85xx_pci_err",330		.suppress_bind_attrs = true,331	},332};333#endif				/* CONFIG_PCI */334 335/**************************** L2 Err device ***************************/336 337/************************ L2 SYSFS parts ***********************************/338 339static ssize_t mpc85xx_l2_inject_data_hi_show(struct edac_device_ctl_info340					      *edac_dev, char *data)341{342	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;343	return sprintf(data, "0x%08x",344		       in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI));345}346 347static ssize_t mpc85xx_l2_inject_data_lo_show(struct edac_device_ctl_info348					      *edac_dev, char *data)349{350	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;351	return sprintf(data, "0x%08x",352		       in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO));353}354 355static ssize_t mpc85xx_l2_inject_ctrl_show(struct edac_device_ctl_info356					   *edac_dev, char *data)357{358	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;359	return sprintf(data, "0x%08x",360		       in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL));361}362 363static ssize_t mpc85xx_l2_inject_data_hi_store(struct edac_device_ctl_info364					       *edac_dev, const char *data,365					       size_t count)366{367	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;368	if (isdigit(*data)) {369		out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI,370			 simple_strtoul(data, NULL, 0));371		return count;372	}373	return 0;374}375 376static ssize_t mpc85xx_l2_inject_data_lo_store(struct edac_device_ctl_info377					       *edac_dev, const char *data,378					       size_t count)379{380	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;381	if (isdigit(*data)) {382		out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO,383			 simple_strtoul(data, NULL, 0));384		return count;385	}386	return 0;387}388 389static ssize_t mpc85xx_l2_inject_ctrl_store(struct edac_device_ctl_info390					    *edac_dev, const char *data,391					    size_t count)392{393	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;394	if (isdigit(*data)) {395		out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL,396			 simple_strtoul(data, NULL, 0));397		return count;398	}399	return 0;400}401 402static struct edac_dev_sysfs_attribute mpc85xx_l2_sysfs_attributes[] = {403	{404	 .attr = {405		  .name = "inject_data_hi",406		  .mode = (S_IRUGO | S_IWUSR)407		  },408	 .show = mpc85xx_l2_inject_data_hi_show,409	 .store = mpc85xx_l2_inject_data_hi_store},410	{411	 .attr = {412		  .name = "inject_data_lo",413		  .mode = (S_IRUGO | S_IWUSR)414		  },415	 .show = mpc85xx_l2_inject_data_lo_show,416	 .store = mpc85xx_l2_inject_data_lo_store},417	{418	 .attr = {419		  .name = "inject_ctrl",420		  .mode = (S_IRUGO | S_IWUSR)421		  },422	 .show = mpc85xx_l2_inject_ctrl_show,423	 .store = mpc85xx_l2_inject_ctrl_store},424 425	/* End of list */426	{427	 .attr = {.name = NULL}428	 }429};430 431static void mpc85xx_set_l2_sysfs_attributes(struct edac_device_ctl_info432					    *edac_dev)433{434	edac_dev->sysfs_attributes = mpc85xx_l2_sysfs_attributes;435}436 437/***************************** L2 ops ***********************************/438 439static void mpc85xx_l2_check(struct edac_device_ctl_info *edac_dev)440{441	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;442	u32 err_detect;443 444	err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);445 446	if (!(err_detect & L2_EDE_MASK))447		return;448 449	pr_err("ECC Error in CPU L2 cache\n");450	pr_err("L2 Error Detect Register: 0x%08x\n", err_detect);451	pr_err("L2 Error Capture Data High Register: 0x%08x\n",452	       in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATAHI));453	pr_err("L2 Error Capture Data Lo Register: 0x%08x\n",454	       in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATALO));455	pr_err("L2 Error Syndrome Register: 0x%08x\n",456	       in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTECC));457	pr_err("L2 Error Attributes Capture Register: 0x%08x\n",458	       in_be32(pdata->l2_vbase + MPC85XX_L2_ERRATTR));459	pr_err("L2 Error Address Capture Register: 0x%08x\n",460	       in_be32(pdata->l2_vbase + MPC85XX_L2_ERRADDR));461 462	/* clear error detect register */463	out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, err_detect);464 465	if (err_detect & L2_EDE_CE_MASK)466		edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);467 468	if (err_detect & L2_EDE_UE_MASK)469		edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);470}471 472static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id)473{474	struct edac_device_ctl_info *edac_dev = dev_id;475	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;476	u32 err_detect;477 478	err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);479 480	if (!(err_detect & L2_EDE_MASK))481		return IRQ_NONE;482 483	mpc85xx_l2_check(edac_dev);484 485	return IRQ_HANDLED;486}487 488static int mpc85xx_l2_err_probe(struct platform_device *op)489{490	struct edac_device_ctl_info *edac_dev;491	struct mpc85xx_l2_pdata *pdata;492	struct resource r;493	int res;494 495	if (!devres_open_group(&op->dev, mpc85xx_l2_err_probe, GFP_KERNEL))496		return -ENOMEM;497 498	edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),499					      "cpu", 1, "L", 1, 2,500					      edac_dev_idx);501	if (!edac_dev) {502		devres_release_group(&op->dev, mpc85xx_l2_err_probe);503		return -ENOMEM;504	}505 506	pdata = edac_dev->pvt_info;507	pdata->name = "mpc85xx_l2_err";508	edac_dev->dev = &op->dev;509	dev_set_drvdata(edac_dev->dev, edac_dev);510	edac_dev->ctl_name = pdata->name;511	edac_dev->dev_name = pdata->name;512 513	res = of_address_to_resource(op->dev.of_node, 0, &r);514	if (res) {515		pr_err("%s: Unable to get resource for L2 err regs\n", __func__);516		goto err;517	}518 519	/* we only need the error registers */520	r.start += 0xe00;521 522	if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),523				     pdata->name)) {524		pr_err("%s: Error while requesting mem region\n", __func__);525		res = -EBUSY;526		goto err;527	}528 529	pdata->l2_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));530	if (!pdata->l2_vbase) {531		pr_err("%s: Unable to setup L2 err regs\n", __func__);532		res = -ENOMEM;533		goto err;534	}535 536	out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, ~0);537 538	orig_l2_err_disable = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS);539 540	/* clear the err_dis */541	out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, 0);542 543	edac_dev->mod_name = EDAC_MOD_STR;544 545	if (edac_op_state == EDAC_OPSTATE_POLL)546		edac_dev->edac_check = mpc85xx_l2_check;547 548	mpc85xx_set_l2_sysfs_attributes(edac_dev);549 550	pdata->edac_idx = edac_dev_idx++;551 552	if (edac_device_add_device(edac_dev) > 0) {553		edac_dbg(3, "failed edac_device_add_device()\n");554		goto err;555	}556 557	if (edac_op_state == EDAC_OPSTATE_INT) {558		pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);559		res = devm_request_irq(&op->dev, pdata->irq,560				       mpc85xx_l2_isr, IRQF_SHARED,561				       "[EDAC] L2 err", edac_dev);562		if (res < 0) {563			pr_err("%s: Unable to request irq %d for MPC85xx L2 err\n",564				__func__, pdata->irq);565			irq_dispose_mapping(pdata->irq);566			res = -ENODEV;567			goto err2;568		}569 570		pr_info(EDAC_MOD_STR " acquired irq %d for L2 Err\n", pdata->irq);571 572		edac_dev->op_state = OP_RUNNING_INTERRUPT;573 574		out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, L2_EIE_MASK);575	}576 577	devres_remove_group(&op->dev, mpc85xx_l2_err_probe);578 579	edac_dbg(3, "success\n");580	pr_info(EDAC_MOD_STR " L2 err registered\n");581 582	return 0;583 584err2:585	edac_device_del_device(&op->dev);586err:587	devres_release_group(&op->dev, mpc85xx_l2_err_probe);588	edac_device_free_ctl_info(edac_dev);589	return res;590}591 592static void mpc85xx_l2_err_remove(struct platform_device *op)593{594	struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev);595	struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;596 597	edac_dbg(0, "\n");598 599	if (edac_op_state == EDAC_OPSTATE_INT) {600		out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0);601		irq_dispose_mapping(pdata->irq);602	}603 604	out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, orig_l2_err_disable);605	edac_device_del_device(&op->dev);606	edac_device_free_ctl_info(edac_dev);607}608 609static const struct of_device_id mpc85xx_l2_err_of_match[] = {610	{ .compatible = "fsl,mpc8536-l2-cache-controller", },611	{ .compatible = "fsl,mpc8540-l2-cache-controller", },612	{ .compatible = "fsl,mpc8541-l2-cache-controller", },613	{ .compatible = "fsl,mpc8544-l2-cache-controller", },614	{ .compatible = "fsl,mpc8548-l2-cache-controller", },615	{ .compatible = "fsl,mpc8555-l2-cache-controller", },616	{ .compatible = "fsl,mpc8560-l2-cache-controller", },617	{ .compatible = "fsl,mpc8568-l2-cache-controller", },618	{ .compatible = "fsl,mpc8569-l2-cache-controller", },619	{ .compatible = "fsl,mpc8572-l2-cache-controller", },620	{ .compatible = "fsl,p1020-l2-cache-controller", },621	{ .compatible = "fsl,p1021-l2-cache-controller", },622	{ .compatible = "fsl,p2020-l2-cache-controller", },623	{ .compatible = "fsl,t2080-l2-cache-controller", },624	{},625};626MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);627 628static struct platform_driver mpc85xx_l2_err_driver = {629	.probe = mpc85xx_l2_err_probe,630	.remove_new = mpc85xx_l2_err_remove,631	.driver = {632		.name = "mpc85xx_l2_err",633		.of_match_table = mpc85xx_l2_err_of_match,634	},635};636 637static const struct of_device_id mpc85xx_mc_err_of_match[] = {638	{ .compatible = "fsl,mpc8536-memory-controller", },639	{ .compatible = "fsl,mpc8540-memory-controller", },640	{ .compatible = "fsl,mpc8541-memory-controller", },641	{ .compatible = "fsl,mpc8544-memory-controller", },642	{ .compatible = "fsl,mpc8548-memory-controller", },643	{ .compatible = "fsl,mpc8555-memory-controller", },644	{ .compatible = "fsl,mpc8560-memory-controller", },645	{ .compatible = "fsl,mpc8568-memory-controller", },646	{ .compatible = "fsl,mpc8569-memory-controller", },647	{ .compatible = "fsl,mpc8572-memory-controller", },648	{ .compatible = "fsl,mpc8349-memory-controller", },649	{ .compatible = "fsl,p1020-memory-controller", },650	{ .compatible = "fsl,p1021-memory-controller", },651	{ .compatible = "fsl,p2020-memory-controller", },652	{ .compatible = "fsl,qoriq-memory-controller", },653	{},654};655MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);656 657static struct platform_driver mpc85xx_mc_err_driver = {658	.probe = fsl_mc_err_probe,659	.remove_new = fsl_mc_err_remove,660	.driver = {661		.name = "mpc85xx_mc_err",662		.of_match_table = mpc85xx_mc_err_of_match,663	},664};665 666static struct platform_driver * const drivers[] = {667	&mpc85xx_mc_err_driver,668	&mpc85xx_l2_err_driver,669#ifdef CONFIG_PCI670	&mpc85xx_pci_err_driver,671#endif672};673 674static int __init mpc85xx_mc_init(void)675{676	int res = 0;677	u32 __maybe_unused pvr = 0;678 679	pr_info("Freescale(R) MPC85xx EDAC driver, (C) 2006 Montavista Software\n");680 681	/* make sure error reporting method is sane */682	switch (edac_op_state) {683	case EDAC_OPSTATE_POLL:684	case EDAC_OPSTATE_INT:685		break;686	default:687		edac_op_state = EDAC_OPSTATE_INT;688		break;689	}690 691	res = platform_register_drivers(drivers, ARRAY_SIZE(drivers));692	if (res)693		pr_warn(EDAC_MOD_STR "drivers fail to register\n");694 695	return 0;696}697 698module_init(mpc85xx_mc_init);699 700static void __exit mpc85xx_mc_exit(void)701{702	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));703}704 705module_exit(mpc85xx_mc_exit);706 707MODULE_DESCRIPTION("Freescale MPC85xx Memory Controller EDAC driver");708MODULE_LICENSE("GPL");709MODULE_AUTHOR("Montavista Software, Inc.");710module_param(edac_op_state, int, 0444);711MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll, 2=Interrupt");712