From: York Sun <york.sun@nxp.com>
To: <linux-edac@vger.kernel.org>
Cc: <morbidrsa@gmail.com>, <oss@buserror.net>, <stuart.yoder@nxp.com>,
<bp@alien8.de>, York Sun <york.sun@nxp.com>,
Doug Thompson <dougthompson@xmission.com>, <mchehab@kernel.org>,
<linux-kernel@vger.kernel.org>
Subject: [Patch v4 3/9] driver/edac/fsl-ddr: Separate FSL DDR EDAC driver from MPC85xx
Date: Tue, 9 Aug 2016 14:55:40 -0700 [thread overview]
Message-ID: <1470779760-16483-4-git-send-email-york.sun@nxp.com> (raw)
In-Reply-To: <1470779760-16483-1-git-send-email-york.sun@nxp.com>
The mpc85xx compatible DDR controllers are used on ARM-based SoCs.
Separate the DDR part from mpc85xx EDAC driver and prepare to support
both architecture.
Signed-off-by: York Sun <york.sun@nxp.com>
---
Change log
v4: Change comment in file header
Use lower case "fsl_ddr_edac" for EDAC_MOD_STR
Drop exporting probe and remove symbols
v3: Fix compiling errors and warnings caused by patch ordering
v2: Reordered patch
Separate FSL DDR commont code as shared object, not another driver
This patch is generated with "git format-patch -M40 -C40" to show
copy-and-delete.
drivers/edac/Makefile | 5 +-
drivers/edac/{mpc85xx_edac.c => fsl_ddr_edac.c} | 701 +-----------------------
drivers/edac/{mpc85xx_edac.h => fsl_ddr_edac.h} | 110 +---
drivers/edac/mpc85xx_edac.c | 559 +------------------
drivers/edac/mpc85xx_edac.h | 66 ---
5 files changed, 28 insertions(+), 1413 deletions(-)
copy drivers/edac/{mpc85xx_edac.c => fsl_ddr_edac.c} (43%)
copy drivers/edac/{mpc85xx_edac.h => fsl_ddr_edac.h} (43%)
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index f9e4a3e..ee047a4 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -50,7 +50,10 @@ amd64_edac_mod-$(CONFIG_EDAC_AMD64_ERROR_INJECTION) += amd64_edac_inj.o
obj-$(CONFIG_EDAC_AMD64) += amd64_edac_mod.o
obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o
-obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac.o
+
+mpc85xx_edac_mod-y := fsl_ddr_edac.o mpc85xx_edac.o
+obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac_mod.o
+
obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o
obj-$(CONFIG_EDAC_CELL) += cell_edac.o
obj-$(CONFIG_EDAC_PPC4XX) += ppc4xx_edac.o
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/fsl_ddr_edac.c
similarity index 43%
copy from drivers/edac/mpc85xx_edac.c
copy to drivers/edac/fsl_ddr_edac.c
index c0b0951..ca7636f 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -1,5 +1,9 @@
/*
- * Freescale MPC85xx Memory Controller kernel module
+ * Freescale Memory Controller kernel module
+ *
+ * Support Power-based SoCs including MPC85xx, MPC86xx, MPC83xx and
+ * ARM-based Layerscape SoCs including LS2xxx. Originally split
+ * out from mpc85xx_edac EDAC driver.
*
* Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc.
*
@@ -20,33 +24,20 @@
#include <linux/edac.h>
#include <linux/smp.h>
#include <linux/gfp.h>
-#include <linux/fsl/edac.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include "edac_module.h"
#include "edac_core.h"
-#include "mpc85xx_edac.h"
+#include "fsl_ddr_edac.h"
+
+#define EDAC_MOD_STR "fsl_ddr_edac"
-static int edac_dev_idx;
-#ifdef CONFIG_PCI
-static int edac_pci_idx;
-#endif
static int edac_mc_idx;
static u32 orig_ddr_err_disable;
static u32 orig_ddr_err_sbe;
-/*
- * PCI Err defines
- */
-#ifdef CONFIG_PCI
-static u32 orig_pci_err_cap_dr;
-static u32 orig_pci_err_en;
-#endif
-
-static u32 orig_l2_err_disable;
-
/************************ MC SYSFS parts ***********************************/
#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
@@ -141,589 +132,6 @@ static struct attribute *mpc85xx_dev_attrs[] = {
ATTRIBUTE_GROUPS(mpc85xx_dev);
-/**************************** PCI Err device ***************************/
-#ifdef CONFIG_PCI
-
-static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
-{
- struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
- u32 err_detect;
-
- err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
-
- /* master aborts can happen during PCI config cycles */
- if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
- return;
- }
-
- pr_err("PCI error(s) detected\n");
- pr_err("PCI/X ERR_DR register: %#08x\n", err_detect);
-
- pr_err("PCI/X ERR_ATTRIB register: %#08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
- pr_err("PCI/X ERR_ADDR register: %#08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
- pr_err("PCI/X ERR_EXT_ADDR register: %#08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
- pr_err("PCI/X ERR_DL register: %#08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
- pr_err("PCI/X ERR_DH register: %#08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
-
- /* clear error bits */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-
- if (err_detect & PCI_EDE_PERR_MASK)
- edac_pci_handle_pe(pci, pci->ctl_name);
-
- if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK)
- edac_pci_handle_npe(pci, pci->ctl_name);
-}
-
-static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
-{
- struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
- u32 err_detect;
-
- err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
-
- pr_err("PCIe error(s) detected\n");
- pr_err("PCIe ERR_DR register: 0x%08x\n", err_detect);
- pr_err("PCIe ERR_CAP_STAT register: 0x%08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR));
- pr_err("PCIe ERR_CAP_R0 register: 0x%08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));
- pr_err("PCIe ERR_CAP_R1 register: 0x%08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));
- pr_err("PCIe ERR_CAP_R2 register: 0x%08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));
- pr_err("PCIe ERR_CAP_R3 register: 0x%08x\n",
- in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));
-
- /* clear error bits */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-}
-
-static int mpc85xx_pcie_find_capability(struct device_node *np)
-{
- struct pci_controller *hose;
-
- if (!np)
- return -EINVAL;
-
- hose = pci_find_hose_for_OF_device(np);
-
- return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
-}
-
-static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
-{
- struct edac_pci_ctl_info *pci = dev_id;
- struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
- u32 err_detect;
-
- err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
-
- if (!err_detect)
- return IRQ_NONE;
-
- if (pdata->is_pcie)
- mpc85xx_pcie_check(pci);
- else
- mpc85xx_pci_check(pci);
-
- return IRQ_HANDLED;
-}
-
-static int mpc85xx_pci_err_probe(struct platform_device *op)
-{
- struct edac_pci_ctl_info *pci;
- struct mpc85xx_pci_pdata *pdata;
- struct mpc85xx_edac_pci_plat_data *plat_data;
- struct device_node *of_node;
- struct resource r;
- int res = 0;
-
- if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
- return -ENOMEM;
-
- pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err");
- if (!pci)
- return -ENOMEM;
-
- /* make sure error reporting method is sane */
- switch (edac_op_state) {
- case EDAC_OPSTATE_POLL:
- case EDAC_OPSTATE_INT:
- break;
- default:
- edac_op_state = EDAC_OPSTATE_INT;
- break;
- }
-
- pdata = pci->pvt_info;
- pdata->name = "mpc85xx_pci_err";
- pdata->irq = NO_IRQ;
-
- plat_data = op->dev.platform_data;
- if (!plat_data) {
- dev_err(&op->dev, "no platform data");
- res = -ENXIO;
- goto err;
- }
- of_node = plat_data->of_node;
-
- if (mpc85xx_pcie_find_capability(of_node) > 0)
- pdata->is_pcie = true;
-
- dev_set_drvdata(&op->dev, pci);
- pci->dev = &op->dev;
- pci->mod_name = EDAC_MOD_STR;
- pci->ctl_name = pdata->name;
- pci->dev_name = dev_name(&op->dev);
-
- if (edac_op_state == EDAC_OPSTATE_POLL) {
- if (pdata->is_pcie)
- pci->edac_check = mpc85xx_pcie_check;
- else
- pci->edac_check = mpc85xx_pci_check;
- }
-
- pdata->edac_idx = edac_pci_idx++;
-
- res = of_address_to_resource(of_node, 0, &r);
- if (res) {
- pr_err("%s: Unable to get resource for "
- "PCI err regs\n", __func__);
- goto err;
- }
-
- /* we only need the error registers */
- r.start += 0xe00;
-
- if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
- pdata->name)) {
- pr_err("%s: Error while requesting mem region\n",
- __func__);
- res = -EBUSY;
- goto err;
- }
-
- pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
- if (!pdata->pci_vbase) {
- pr_err("%s: Unable to setup PCI err regs\n", __func__);
- res = -ENOMEM;
- goto err;
- }
-
- if (pdata->is_pcie) {
- orig_pci_err_cap_dr =
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR);
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0);
- orig_pci_err_en =
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0);
- } else {
- orig_pci_err_cap_dr =
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
-
- /* PCI master abort is expected during config cycles */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
-
- orig_pci_err_en =
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
-
- /* disable master abort reporting */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
- }
-
- /* clear error bits */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
-
- if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
- edac_dbg(3, "failed edac_pci_add_device()\n");
- goto err;
- }
-
- if (edac_op_state == EDAC_OPSTATE_INT) {
- pdata->irq = irq_of_parse_and_map(of_node, 0);
- res = devm_request_irq(&op->dev, pdata->irq,
- mpc85xx_pci_isr,
- IRQF_SHARED,
- "[EDAC] PCI err", pci);
- if (res < 0) {
- pr_err("%s: Unable to request irq %d for "
- "MPC85xx PCI err\n", __func__, pdata->irq);
- irq_dispose_mapping(pdata->irq);
- res = -ENODEV;
- goto err2;
- }
-
- pr_info(EDAC_MOD_STR " acquired irq %d for PCI Err\n",
- pdata->irq);
- }
-
- if (pdata->is_pcie) {
- /*
- * Enable all PCIe error interrupt & error detect except invalid
- * PEX_CONFIG_ADDR/PEX_CONFIG_DATA access interrupt generation
- * enable bit and invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access
- * detection enable bit. Because PCIe bus code to initialize and
- * configure these PCIe devices on booting will use some invalid
- * PEX_CONFIG_ADDR/PEX_CONFIG_DATA, edac driver prints the much
- * notice information. So disable this detect to fix ugly print.
- */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0
- & ~PEX_ERR_ICCAIE_EN_BIT);
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0
- | PEX_ERR_ICCAD_DISR_BIT);
- }
-
- devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
- edac_dbg(3, "success\n");
- pr_info(EDAC_MOD_STR " PCI err registered\n");
-
- return 0;
-
-err2:
- edac_pci_del_device(&op->dev);
-err:
- edac_pci_free_ctl_info(pci);
- devres_release_group(&op->dev, mpc85xx_pci_err_probe);
- return res;
-}
-
-static const struct platform_device_id mpc85xx_pci_err_match[] = {
- {
- .name = "mpc85xx-pci-edac"
- },
- {}
-};
-
-static struct platform_driver mpc85xx_pci_err_driver = {
- .probe = mpc85xx_pci_err_probe,
- .id_table = mpc85xx_pci_err_match,
- .driver = {
- .name = "mpc85xx_pci_err",
- .suppress_bind_attrs = true,
- },
-};
-#endif /* CONFIG_PCI */
-
-/**************************** L2 Err device ***************************/
-
-/************************ L2 SYSFS parts ***********************************/
-
-static ssize_t mpc85xx_l2_inject_data_hi_show(struct edac_device_ctl_info
- *edac_dev, char *data)
-{
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- return sprintf(data, "0x%08x",
- in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI));
-}
-
-static ssize_t mpc85xx_l2_inject_data_lo_show(struct edac_device_ctl_info
- *edac_dev, char *data)
-{
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- return sprintf(data, "0x%08x",
- in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO));
-}
-
-static ssize_t mpc85xx_l2_inject_ctrl_show(struct edac_device_ctl_info
- *edac_dev, char *data)
-{
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- return sprintf(data, "0x%08x",
- in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL));
-}
-
-static ssize_t mpc85xx_l2_inject_data_hi_store(struct edac_device_ctl_info
- *edac_dev, const char *data,
- size_t count)
-{
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- if (isdigit(*data)) {
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI,
- simple_strtoul(data, NULL, 0));
- return count;
- }
- return 0;
-}
-
-static ssize_t mpc85xx_l2_inject_data_lo_store(struct edac_device_ctl_info
- *edac_dev, const char *data,
- size_t count)
-{
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- if (isdigit(*data)) {
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO,
- simple_strtoul(data, NULL, 0));
- return count;
- }
- return 0;
-}
-
-static ssize_t mpc85xx_l2_inject_ctrl_store(struct edac_device_ctl_info
- *edac_dev, const char *data,
- size_t count)
-{
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- if (isdigit(*data)) {
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL,
- simple_strtoul(data, NULL, 0));
- return count;
- }
- return 0;
-}
-
-static struct edac_dev_sysfs_attribute mpc85xx_l2_sysfs_attributes[] = {
- {
- .attr = {
- .name = "inject_data_hi",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = mpc85xx_l2_inject_data_hi_show,
- .store = mpc85xx_l2_inject_data_hi_store},
- {
- .attr = {
- .name = "inject_data_lo",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = mpc85xx_l2_inject_data_lo_show,
- .store = mpc85xx_l2_inject_data_lo_store},
- {
- .attr = {
- .name = "inject_ctrl",
- .mode = (S_IRUGO | S_IWUSR)
- },
- .show = mpc85xx_l2_inject_ctrl_show,
- .store = mpc85xx_l2_inject_ctrl_store},
-
- /* End of list */
- {
- .attr = {.name = NULL}
- }
-};
-
-static void mpc85xx_set_l2_sysfs_attributes(struct edac_device_ctl_info
- *edac_dev)
-{
- edac_dev->sysfs_attributes = mpc85xx_l2_sysfs_attributes;
-}
-
-/***************************** L2 ops ***********************************/
-
-static void mpc85xx_l2_check(struct edac_device_ctl_info *edac_dev)
-{
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- u32 err_detect;
-
- err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);
-
- if (!(err_detect & L2_EDE_MASK))
- return;
-
- pr_err("ECC Error in CPU L2 cache\n");
- pr_err("L2 Error Detect Register: 0x%08x\n", err_detect);
- pr_err("L2 Error Capture Data High Register: 0x%08x\n",
- in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATAHI));
- pr_err("L2 Error Capture Data Lo Register: 0x%08x\n",
- in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATALO));
- pr_err("L2 Error Syndrome Register: 0x%08x\n",
- in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTECC));
- pr_err("L2 Error Attributes Capture Register: 0x%08x\n",
- in_be32(pdata->l2_vbase + MPC85XX_L2_ERRATTR));
- pr_err("L2 Error Address Capture Register: 0x%08x\n",
- in_be32(pdata->l2_vbase + MPC85XX_L2_ERRADDR));
-
- /* clear error detect register */
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, err_detect);
-
- if (err_detect & L2_EDE_CE_MASK)
- edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
-
- if (err_detect & L2_EDE_UE_MASK)
- edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
-}
-
-static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id)
-{
- struct edac_device_ctl_info *edac_dev = dev_id;
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
- u32 err_detect;
-
- err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);
-
- if (!(err_detect & L2_EDE_MASK))
- return IRQ_NONE;
-
- mpc85xx_l2_check(edac_dev);
-
- return IRQ_HANDLED;
-}
-
-static int mpc85xx_l2_err_probe(struct platform_device *op)
-{
- struct edac_device_ctl_info *edac_dev;
- struct mpc85xx_l2_pdata *pdata;
- struct resource r;
- int res;
-
- if (!devres_open_group(&op->dev, mpc85xx_l2_err_probe, GFP_KERNEL))
- return -ENOMEM;
-
- edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
- "cpu", 1, "L", 1, 2, NULL, 0,
- edac_dev_idx);
- if (!edac_dev) {
- devres_release_group(&op->dev, mpc85xx_l2_err_probe);
- return -ENOMEM;
- }
-
- pdata = edac_dev->pvt_info;
- pdata->name = "mpc85xx_l2_err";
- pdata->irq = NO_IRQ;
- edac_dev->dev = &op->dev;
- dev_set_drvdata(edac_dev->dev, edac_dev);
- edac_dev->ctl_name = pdata->name;
- edac_dev->dev_name = pdata->name;
-
- res = of_address_to_resource(op->dev.of_node, 0, &r);
- if (res) {
- pr_err("%s: Unable to get resource for "
- "L2 err regs\n", __func__);
- goto err;
- }
-
- /* we only need the error registers */
- r.start += 0xe00;
-
- if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
- pdata->name)) {
- pr_err("%s: Error while requesting mem region\n",
- __func__);
- res = -EBUSY;
- goto err;
- }
-
- pdata->l2_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
- if (!pdata->l2_vbase) {
- pr_err("%s: Unable to setup L2 err regs\n", __func__);
- res = -ENOMEM;
- goto err;
- }
-
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, ~0);
-
- orig_l2_err_disable = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS);
-
- /* clear the err_dis */
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, 0);
-
- edac_dev->mod_name = EDAC_MOD_STR;
-
- if (edac_op_state == EDAC_OPSTATE_POLL)
- edac_dev->edac_check = mpc85xx_l2_check;
-
- mpc85xx_set_l2_sysfs_attributes(edac_dev);
-
- pdata->edac_idx = edac_dev_idx++;
-
- if (edac_device_add_device(edac_dev) > 0) {
- edac_dbg(3, "failed edac_device_add_device()\n");
- goto err;
- }
-
- if (edac_op_state == EDAC_OPSTATE_INT) {
- pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
- res = devm_request_irq(&op->dev, pdata->irq,
- mpc85xx_l2_isr, IRQF_SHARED,
- "[EDAC] L2 err", edac_dev);
- if (res < 0) {
- pr_err("%s: Unable to request irq %d for "
- "MPC85xx L2 err\n", __func__, pdata->irq);
- irq_dispose_mapping(pdata->irq);
- res = -ENODEV;
- goto err2;
- }
-
- pr_info(EDAC_MOD_STR " acquired irq %d for L2 Err\n",
- pdata->irq);
-
- edac_dev->op_state = OP_RUNNING_INTERRUPT;
-
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, L2_EIE_MASK);
- }
-
- devres_remove_group(&op->dev, mpc85xx_l2_err_probe);
-
- edac_dbg(3, "success\n");
- pr_info(EDAC_MOD_STR " L2 err registered\n");
-
- return 0;
-
-err2:
- edac_device_del_device(&op->dev);
-err:
- devres_release_group(&op->dev, mpc85xx_l2_err_probe);
- edac_device_free_ctl_info(edac_dev);
- return res;
-}
-
-static int mpc85xx_l2_err_remove(struct platform_device *op)
-{
- struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev);
- struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
-
- edac_dbg(0, "\n");
-
- if (edac_op_state == EDAC_OPSTATE_INT) {
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0);
- irq_dispose_mapping(pdata->irq);
- }
-
- out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, orig_l2_err_disable);
- edac_device_del_device(&op->dev);
- edac_device_free_ctl_info(edac_dev);
- return 0;
-}
-
-static const struct of_device_id mpc85xx_l2_err_of_match[] = {
-/* deprecate the fsl,85.. forms in the future, 2.6.30? */
- { .compatible = "fsl,8540-l2-cache-controller", },
- { .compatible = "fsl,8541-l2-cache-controller", },
- { .compatible = "fsl,8544-l2-cache-controller", },
- { .compatible = "fsl,8548-l2-cache-controller", },
- { .compatible = "fsl,8555-l2-cache-controller", },
- { .compatible = "fsl,8568-l2-cache-controller", },
- { .compatible = "fsl,mpc8536-l2-cache-controller", },
- { .compatible = "fsl,mpc8540-l2-cache-controller", },
- { .compatible = "fsl,mpc8541-l2-cache-controller", },
- { .compatible = "fsl,mpc8544-l2-cache-controller", },
- { .compatible = "fsl,mpc8548-l2-cache-controller", },
- { .compatible = "fsl,mpc8555-l2-cache-controller", },
- { .compatible = "fsl,mpc8560-l2-cache-controller", },
- { .compatible = "fsl,mpc8568-l2-cache-controller", },
- { .compatible = "fsl,mpc8569-l2-cache-controller", },
- { .compatible = "fsl,mpc8572-l2-cache-controller", },
- { .compatible = "fsl,p1020-l2-cache-controller", },
- { .compatible = "fsl,p1021-l2-cache-controller", },
- { .compatible = "fsl,p2020-l2-cache-controller", },
- {},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
-
-static struct platform_driver mpc85xx_l2_err_driver = {
- .probe = mpc85xx_l2_err_probe,
- .remove = mpc85xx_l2_err_remove,
- .driver = {
- .name = "mpc85xx_l2_err",
- .of_match_table = mpc85xx_l2_err_of_match,
- },
-};
-
/**************************** MC Err device ***************************/
/*
@@ -1026,7 +434,7 @@ static void mpc85xx_init_csrows(struct mem_ctl_info *mci)
}
}
-static int mpc85xx_mc_err_probe(struct platform_device *op)
+int mpc85xx_mc_err_probe(struct platform_device *op)
{
struct mem_ctl_info *mci;
struct edac_mc_layer layers[2];
@@ -1096,7 +504,6 @@ static int mpc85xx_mc_err_probe(struct platform_device *op)
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
mci->mod_name = EDAC_MOD_STR;
- mci->mod_ver = MPC85XX_REVISION;
if (edac_op_state == EDAC_OPSTATE_POLL)
mci->edac_check = mpc85xx_mc_check;
@@ -1138,8 +545,8 @@ static int mpc85xx_mc_err_probe(struct platform_device *op)
IRQF_SHARED,
"[EDAC] MC err", mci);
if (res < 0) {
- pr_err("%s: Unable to request irq %d for "
- "MPC85xx DRAM ERR\n", __func__, pdata->irq);
+ pr_err("%s: Unable to request irq %d for MPC85xx DRAM ERR\n",
+ __func__, pdata->irq);
irq_dispose_mapping(pdata->irq);
res = -ENODEV;
goto err2;
@@ -1163,7 +570,7 @@ err:
return res;
}
-static int mpc85xx_mc_err_remove(struct platform_device *op)
+int mpc85xx_mc_err_remove(struct platform_device *op)
{
struct mem_ctl_info *mci = dev_get_drvdata(&op->dev);
struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
@@ -1183,87 +590,3 @@ static int mpc85xx_mc_err_remove(struct platform_device *op)
edac_mc_free(mci);
return 0;
}
-
-static const struct of_device_id mpc85xx_mc_err_of_match[] = {
-/* deprecate the fsl,85.. forms in the future, 2.6.30? */
- { .compatible = "fsl,8540-memory-controller", },
- { .compatible = "fsl,8541-memory-controller", },
- { .compatible = "fsl,8544-memory-controller", },
- { .compatible = "fsl,8548-memory-controller", },
- { .compatible = "fsl,8555-memory-controller", },
- { .compatible = "fsl,8568-memory-controller", },
- { .compatible = "fsl,mpc8536-memory-controller", },
- { .compatible = "fsl,mpc8540-memory-controller", },
- { .compatible = "fsl,mpc8541-memory-controller", },
- { .compatible = "fsl,mpc8544-memory-controller", },
- { .compatible = "fsl,mpc8548-memory-controller", },
- { .compatible = "fsl,mpc8555-memory-controller", },
- { .compatible = "fsl,mpc8560-memory-controller", },
- { .compatible = "fsl,mpc8568-memory-controller", },
- { .compatible = "fsl,mpc8569-memory-controller", },
- { .compatible = "fsl,mpc8572-memory-controller", },
- { .compatible = "fsl,mpc8349-memory-controller", },
- { .compatible = "fsl,p1020-memory-controller", },
- { .compatible = "fsl,p1021-memory-controller", },
- { .compatible = "fsl,p2020-memory-controller", },
- { .compatible = "fsl,qoriq-memory-controller", },
- {},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
-
-static struct platform_driver mpc85xx_mc_err_driver = {
- .probe = mpc85xx_mc_err_probe,
- .remove = mpc85xx_mc_err_remove,
- .driver = {
- .name = "mpc85xx_mc_err",
- .of_match_table = mpc85xx_mc_err_of_match,
- },
-};
-
-static struct platform_driver * const drivers[] = {
- &mpc85xx_mc_err_driver,
- &mpc85xx_l2_err_driver,
-#ifdef CONFIG_PCI
- &mpc85xx_pci_err_driver,
-#endif
-};
-
-static int __init mpc85xx_mc_init(void)
-{
- int res = 0;
- u32 __maybe_unused pvr = 0;
-
- pr_info("Freescale(R) MPC85xx EDAC driver, "
- "(C) 2006 Montavista Software\n");
-
- /* make sure error reporting method is sane */
- switch (edac_op_state) {
- case EDAC_OPSTATE_POLL:
- case EDAC_OPSTATE_INT:
- break;
- default:
- edac_op_state = EDAC_OPSTATE_INT;
- break;
- }
-
- res = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
- if (res)
- pr_warn(EDAC_MOD_STR "drivers fail to register\n");
-
- return 0;
-}
-
-module_init(mpc85xx_mc_init);
-
-static void __exit mpc85xx_mc_exit(void)
-{
- platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
-}
-
-module_exit(mpc85xx_mc_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Montavista Software, Inc.");
-module_param(edac_op_state, int, 0444);
-MODULE_PARM_DESC(edac_op_state,
- "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/fsl_ddr_edac.h
similarity index 43%
copy from drivers/edac/mpc85xx_edac.h
copy to drivers/edac/fsl_ddr_edac.h
index 9352e88..2f2c2b1 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/fsl_ddr_edac.h
@@ -1,5 +1,10 @@
/*
- * Freescale MPC85xx Memory Controller kernel module
+ * Freescale Memory Controller kernel module
+ *
+ * Support Power-based SoCs including MPC85xx, MPC86xx, MPC83xx and
+ * ARM-based Layerscape SoCs including LS2xxx. Originally split
+ * out from mpc85xx_edac EDAC driver.
+ *
* Author: Dave Jiang <djiang@mvista.com>
*
* 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
@@ -8,17 +13,11 @@
* or implied.
*
*/
-#ifndef _MPC85XX_EDAC_H_
-#define _MPC85XX_EDAC_H_
-
-#define MPC85XX_REVISION " Ver: 2.0.0"
-#define EDAC_MOD_STR "MPC85xx_edac"
-
-#define mpc85xx_printk(level, fmt, arg...) \
- edac_printk(level, "MPC85xx", fmt, ##arg)
+#ifndef _FSL_DDR_EDAC_H_
+#define _FSL_DDR_EDAC_H_
#define mpc85xx_mc_printk(mci, level, fmt, arg...) \
- edac_mc_chipset_printk(mci, level, "MPC85xx", fmt, ##arg)
+ edac_mc_chipset_printk(mci, level, "FSL_DDR", fmt, ##arg)
/*
* DRAM error defines
@@ -76,99 +75,12 @@
#define DDR_EDI_SBED 0x4 /* single-bit ECC error disable */
#define DDR_EDI_MBED 0x8 /* multi-bit ECC error disable */
-/*
- * L2 Err defines
- */
-#define MPC85XX_L2_ERRINJHI 0x0000
-#define MPC85XX_L2_ERRINJLO 0x0004
-#define MPC85XX_L2_ERRINJCTL 0x0008
-#define MPC85XX_L2_CAPTDATAHI 0x0020
-#define MPC85XX_L2_CAPTDATALO 0x0024
-#define MPC85XX_L2_CAPTECC 0x0028
-#define MPC85XX_L2_ERRDET 0x0040
-#define MPC85XX_L2_ERRDIS 0x0044
-#define MPC85XX_L2_ERRINTEN 0x0048
-#define MPC85XX_L2_ERRATTR 0x004c
-#define MPC85XX_L2_ERRADDR 0x0050
-#define MPC85XX_L2_ERRCTL 0x0058
-
-/* Error Interrupt Enable */
-#define L2_EIE_L2CFGINTEN 0x1
-#define L2_EIE_SBECCINTEN 0x4
-#define L2_EIE_MBECCINTEN 0x8
-#define L2_EIE_TPARINTEN 0x10
-#define L2_EIE_MASK (L2_EIE_L2CFGINTEN | L2_EIE_SBECCINTEN | \
- L2_EIE_MBECCINTEN | L2_EIE_TPARINTEN)
-
-/* Error Detect */
-#define L2_EDE_L2CFGERR 0x1
-#define L2_EDE_SBECCERR 0x4
-#define L2_EDE_MBECCERR 0x8
-#define L2_EDE_TPARERR 0x10
-#define L2_EDE_MULL2ERR 0x80000000
-
-#define L2_EDE_CE_MASK L2_EDE_SBECCERR
-#define L2_EDE_UE_MASK (L2_EDE_L2CFGERR | L2_EDE_MBECCERR | \
- L2_EDE_TPARERR)
-#define L2_EDE_MASK (L2_EDE_L2CFGERR | L2_EDE_SBECCERR | \
- L2_EDE_MBECCERR | L2_EDE_TPARERR | L2_EDE_MULL2ERR)
-
-/*
- * PCI Err defines
- */
-#define PCI_EDE_TOE 0x00000001
-#define PCI_EDE_SCM 0x00000002
-#define PCI_EDE_IRMSV 0x00000004
-#define PCI_EDE_ORMSV 0x00000008
-#define PCI_EDE_OWMSV 0x00000010
-#define PCI_EDE_TGT_ABRT 0x00000020
-#define PCI_EDE_MST_ABRT 0x00000040
-#define PCI_EDE_TGT_PERR 0x00000080
-#define PCI_EDE_MST_PERR 0x00000100
-#define PCI_EDE_RCVD_SERR 0x00000200
-#define PCI_EDE_ADDR_PERR 0x00000400
-#define PCI_EDE_MULTI_ERR 0x80000000
-
-#define PCI_EDE_PERR_MASK (PCI_EDE_TGT_PERR | PCI_EDE_MST_PERR | \
- PCI_EDE_ADDR_PERR)
-
-#define MPC85XX_PCI_ERR_DR 0x0000
-#define MPC85XX_PCI_ERR_CAP_DR 0x0004
-#define MPC85XX_PCI_ERR_EN 0x0008
-#define PEX_ERR_ICCAIE_EN_BIT 0x00020000
-#define MPC85XX_PCI_ERR_ATTRIB 0x000c
-#define MPC85XX_PCI_ERR_ADDR 0x0010
-#define PEX_ERR_ICCAD_DISR_BIT 0x00020000
-#define MPC85XX_PCI_ERR_EXT_ADDR 0x0014
-#define MPC85XX_PCI_ERR_DL 0x0018
-#define MPC85XX_PCI_ERR_DH 0x001c
-#define MPC85XX_PCI_GAS_TIMR 0x0020
-#define MPC85XX_PCI_PCIX_TIMR 0x0024
-#define MPC85XX_PCIE_ERR_CAP_R0 0x0028
-#define MPC85XX_PCIE_ERR_CAP_R1 0x002c
-#define MPC85XX_PCIE_ERR_CAP_R2 0x0030
-#define MPC85XX_PCIE_ERR_CAP_R3 0x0034
-
struct mpc85xx_mc_pdata {
char *name;
int edac_idx;
void __iomem *mc_vbase;
int irq;
};
-
-struct mpc85xx_l2_pdata {
- char *name;
- int edac_idx;
- void __iomem *l2_vbase;
- int irq;
-};
-
-struct mpc85xx_pci_pdata {
- char *name;
- bool is_pcie;
- int edac_idx;
- void __iomem *pci_vbase;
- int irq;
-};
-
+int mpc85xx_mc_err_probe(struct platform_device *op);
+int mpc85xx_mc_err_remove(struct platform_device *op);
#endif
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index c0b0951..af9ce77 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -27,15 +27,12 @@
#include "edac_module.h"
#include "edac_core.h"
#include "mpc85xx_edac.h"
+#include "fsl_ddr_edac.h"
static int edac_dev_idx;
#ifdef CONFIG_PCI
static int edac_pci_idx;
#endif
-static int edac_mc_idx;
-
-static u32 orig_ddr_err_disable;
-static u32 orig_ddr_err_sbe;
/*
* PCI Err defines
@@ -47,100 +44,6 @@ static u32 orig_pci_err_en;
static u32 orig_l2_err_disable;
-/************************ MC SYSFS parts ***********************************/
-
-#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
-
-static ssize_t mpc85xx_mc_inject_data_hi_show(struct device *dev,
- struct device_attribute *mattr,
- char *data)
-{
- struct mem_ctl_info *mci = to_mci(dev);
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- return sprintf(data, "0x%08x",
- in_be32(pdata->mc_vbase +
- MPC85XX_MC_DATA_ERR_INJECT_HI));
-}
-
-static ssize_t mpc85xx_mc_inject_data_lo_show(struct device *dev,
- struct device_attribute *mattr,
- char *data)
-{
- struct mem_ctl_info *mci = to_mci(dev);
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- return sprintf(data, "0x%08x",
- in_be32(pdata->mc_vbase +
- MPC85XX_MC_DATA_ERR_INJECT_LO));
-}
-
-static ssize_t mpc85xx_mc_inject_ctrl_show(struct device *dev,
- struct device_attribute *mattr,
- char *data)
-{
- struct mem_ctl_info *mci = to_mci(dev);
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- return sprintf(data, "0x%08x",
- in_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT));
-}
-
-static ssize_t mpc85xx_mc_inject_data_hi_store(struct device *dev,
- struct device_attribute *mattr,
- const char *data, size_t count)
-{
- struct mem_ctl_info *mci = to_mci(dev);
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- if (isdigit(*data)) {
- out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI,
- simple_strtoul(data, NULL, 0));
- return count;
- }
- return 0;
-}
-
-static ssize_t mpc85xx_mc_inject_data_lo_store(struct device *dev,
- struct device_attribute *mattr,
- const char *data, size_t count)
-{
- struct mem_ctl_info *mci = to_mci(dev);
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- if (isdigit(*data)) {
- out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO,
- simple_strtoul(data, NULL, 0));
- return count;
- }
- return 0;
-}
-
-static ssize_t mpc85xx_mc_inject_ctrl_store(struct device *dev,
- struct device_attribute *mattr,
- const char *data, size_t count)
-{
- struct mem_ctl_info *mci = to_mci(dev);
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- if (isdigit(*data)) {
- out_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT,
- simple_strtoul(data, NULL, 0));
- return count;
- }
- return 0;
-}
-
-DEVICE_ATTR(inject_data_hi, S_IRUGO | S_IWUSR,
- mpc85xx_mc_inject_data_hi_show, mpc85xx_mc_inject_data_hi_store);
-DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR,
- mpc85xx_mc_inject_data_lo_show, mpc85xx_mc_inject_data_lo_store);
-DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR,
- mpc85xx_mc_inject_ctrl_show, mpc85xx_mc_inject_ctrl_store);
-
-static struct attribute *mpc85xx_dev_attrs[] = {
- &dev_attr_inject_data_hi.attr,
- &dev_attr_inject_data_lo.attr,
- &dev_attr_inject_ctrl.attr,
- NULL
-};
-
-ATTRIBUTE_GROUPS(mpc85xx_dev);
-
/**************************** PCI Err device ***************************/
#ifdef CONFIG_PCI
@@ -724,466 +627,6 @@ static struct platform_driver mpc85xx_l2_err_driver = {
},
};
-/**************************** MC Err device ***************************/
-
-/*
- * Taken from table 8-55 in the MPC8641 User's Manual and/or 9-61 in the
- * MPC8572 User's Manual. Each line represents a syndrome bit column as a
- * 64-bit value, but split into an upper and lower 32-bit chunk. The labels
- * below correspond to Freescale's manuals.
- */
-static unsigned int ecc_table[16] = {
- /* MSB LSB */
- /* [0:31] [32:63] */
- 0xf00fe11e, 0xc33c0ff7, /* Syndrome bit 7 */
- 0x00ff00ff, 0x00fff0ff,
- 0x0f0f0f0f, 0x0f0fff00,
- 0x11113333, 0x7777000f,
- 0x22224444, 0x8888222f,
- 0x44448888, 0xffff4441,
- 0x8888ffff, 0x11118882,
- 0xffff1111, 0x22221114, /* Syndrome bit 0 */
-};
-
-/*
- * Calculate the correct ECC value for a 64-bit value specified by high:low
- */
-static u8 calculate_ecc(u32 high, u32 low)
-{
- u32 mask_low;
- u32 mask_high;
- int bit_cnt;
- u8 ecc = 0;
- int i;
- int j;
-
- for (i = 0; i < 8; i++) {
- mask_high = ecc_table[i * 2];
- mask_low = ecc_table[i * 2 + 1];
- bit_cnt = 0;
-
- for (j = 0; j < 32; j++) {
- if ((mask_high >> j) & 1)
- bit_cnt ^= (high >> j) & 1;
- if ((mask_low >> j) & 1)
- bit_cnt ^= (low >> j) & 1;
- }
-
- ecc |= bit_cnt << i;
- }
-
- return ecc;
-}
-
-/*
- * Create the syndrome code which is generated if the data line specified by
- * 'bit' failed. Eg generate an 8-bit codes seen in Table 8-55 in the MPC8641
- * User's Manual and 9-61 in the MPC8572 User's Manual.
- */
-static u8 syndrome_from_bit(unsigned int bit) {
- int i;
- u8 syndrome = 0;
-
- /*
- * Cycle through the upper or lower 32-bit portion of each value in
- * ecc_table depending on if 'bit' is in the upper or lower half of
- * 64-bit data.
- */
- for (i = bit < 32; i < 16; i += 2)
- syndrome |= ((ecc_table[i] >> (bit % 32)) & 1) << (i / 2);
-
- return syndrome;
-}
-
-/*
- * Decode data and ecc syndrome to determine what went wrong
- * Note: This can only decode single-bit errors
- */
-static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc,
- int *bad_data_bit, int *bad_ecc_bit)
-{
- int i;
- u8 syndrome;
-
- *bad_data_bit = -1;
- *bad_ecc_bit = -1;
-
- /*
- * Calculate the ECC of the captured data and XOR it with the captured
- * ECC to find an ECC syndrome value we can search for
- */
- syndrome = calculate_ecc(cap_high, cap_low) ^ cap_ecc;
-
- /* Check if a data line is stuck... */
- for (i = 0; i < 64; i++) {
- if (syndrome == syndrome_from_bit(i)) {
- *bad_data_bit = i;
- return;
- }
- }
-
- /* If data is correct, check ECC bits for errors... */
- for (i = 0; i < 8; i++) {
- if ((syndrome >> i) & 0x1) {
- *bad_ecc_bit = i;
- return;
- }
- }
-}
-
-#define make64(high, low) (((u64)(high) << 32) | (low))
-
-static void mpc85xx_mc_check(struct mem_ctl_info *mci)
-{
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- struct csrow_info *csrow;
- u32 bus_width;
- u32 err_detect;
- u32 syndrome;
- u64 err_addr;
- u32 pfn;
- int row_index;
- u32 cap_high;
- u32 cap_low;
- int bad_data_bit;
- int bad_ecc_bit;
-
- err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT);
- if (!err_detect)
- return;
-
- mpc85xx_mc_printk(mci, KERN_ERR, "Err Detect Register: %#8.8x\n",
- err_detect);
-
- /* no more processing if not ECC bit errors */
- if (!(err_detect & (DDR_EDE_SBE | DDR_EDE_MBE))) {
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect);
- return;
- }
-
- syndrome = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ECC);
-
- /* Mask off appropriate bits of syndrome based on bus width */
- bus_width = (in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG) &
- DSC_DBW_MASK) ? 32 : 64;
- if (bus_width == 64)
- syndrome &= 0xff;
- else
- syndrome &= 0xffff;
-
- err_addr = make64(
- in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_EXT_ADDRESS),
- in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS));
- pfn = err_addr >> PAGE_SHIFT;
-
- for (row_index = 0; row_index < mci->nr_csrows; row_index++) {
- csrow = mci->csrows[row_index];
- if ((pfn >= csrow->first_page) && (pfn <= csrow->last_page))
- break;
- }
-
- cap_high = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_HI);
- cap_low = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_LO);
-
- /*
- * Analyze single-bit errors on 64-bit wide buses
- * TODO: Add support for 32-bit wide buses
- */
- if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) {
- sbe_ecc_decode(cap_high, cap_low, syndrome,
- &bad_data_bit, &bad_ecc_bit);
-
- if (bad_data_bit != -1)
- mpc85xx_mc_printk(mci, KERN_ERR,
- "Faulty Data bit: %d\n", bad_data_bit);
- if (bad_ecc_bit != -1)
- mpc85xx_mc_printk(mci, KERN_ERR,
- "Faulty ECC bit: %d\n", bad_ecc_bit);
-
- mpc85xx_mc_printk(mci, KERN_ERR,
- "Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
- cap_high ^ (1 << (bad_data_bit - 32)),
- cap_low ^ (1 << bad_data_bit),
- syndrome ^ (1 << bad_ecc_bit));
- }
-
- mpc85xx_mc_printk(mci, KERN_ERR,
- "Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
- cap_high, cap_low, syndrome);
- mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8llx\n", err_addr);
- mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn);
-
- /* we are out of range */
- if (row_index == mci->nr_csrows)
- mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n");
-
- if (err_detect & DDR_EDE_SBE)
- edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
- pfn, err_addr & ~PAGE_MASK, syndrome,
- row_index, 0, -1,
- mci->ctl_name, "");
-
- if (err_detect & DDR_EDE_MBE)
- edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
- pfn, err_addr & ~PAGE_MASK, syndrome,
- row_index, 0, -1,
- mci->ctl_name, "");
-
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect);
-}
-
-static irqreturn_t mpc85xx_mc_isr(int irq, void *dev_id)
-{
- struct mem_ctl_info *mci = dev_id;
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- u32 err_detect;
-
- err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT);
- if (!err_detect)
- return IRQ_NONE;
-
- mpc85xx_mc_check(mci);
-
- return IRQ_HANDLED;
-}
-
-static void mpc85xx_init_csrows(struct mem_ctl_info *mci)
-{
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
- struct csrow_info *csrow;
- struct dimm_info *dimm;
- u32 sdram_ctl;
- u32 sdtype;
- enum mem_type mtype;
- u32 cs_bnds;
- int index;
-
- sdram_ctl = in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG);
-
- sdtype = sdram_ctl & DSC_SDTYPE_MASK;
- if (sdram_ctl & DSC_RD_EN) {
- switch (sdtype) {
- case DSC_SDTYPE_DDR:
- mtype = MEM_RDDR;
- break;
- case DSC_SDTYPE_DDR2:
- mtype = MEM_RDDR2;
- break;
- case DSC_SDTYPE_DDR3:
- mtype = MEM_RDDR3;
- break;
- default:
- mtype = MEM_UNKNOWN;
- break;
- }
- } else {
- switch (sdtype) {
- case DSC_SDTYPE_DDR:
- mtype = MEM_DDR;
- break;
- case DSC_SDTYPE_DDR2:
- mtype = MEM_DDR2;
- break;
- case DSC_SDTYPE_DDR3:
- mtype = MEM_DDR3;
- break;
- default:
- mtype = MEM_UNKNOWN;
- break;
- }
- }
-
- for (index = 0; index < mci->nr_csrows; index++) {
- u32 start;
- u32 end;
-
- csrow = mci->csrows[index];
- dimm = csrow->channels[0]->dimm;
-
- cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 +
- (index * MPC85XX_MC_CS_BNDS_OFS));
-
- start = (cs_bnds & 0xffff0000) >> 16;
- end = (cs_bnds & 0x0000ffff);
-
- if (start == end)
- continue; /* not populated */
-
- start <<= (24 - PAGE_SHIFT);
- end <<= (24 - PAGE_SHIFT);
- end |= (1 << (24 - PAGE_SHIFT)) - 1;
-
- csrow->first_page = start;
- csrow->last_page = end;
-
- dimm->nr_pages = end + 1 - start;
- dimm->grain = 8;
- dimm->mtype = mtype;
- dimm->dtype = DEV_UNKNOWN;
- if (sdram_ctl & DSC_X32_EN)
- dimm->dtype = DEV_X32;
- dimm->edac_mode = EDAC_SECDED;
- }
-}
-
-static int mpc85xx_mc_err_probe(struct platform_device *op)
-{
- struct mem_ctl_info *mci;
- struct edac_mc_layer layers[2];
- struct mpc85xx_mc_pdata *pdata;
- struct resource r;
- u32 sdram_ctl;
- int res;
-
- if (!devres_open_group(&op->dev, mpc85xx_mc_err_probe, GFP_KERNEL))
- return -ENOMEM;
-
- layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
- layers[0].size = 4;
- layers[0].is_virt_csrow = true;
- layers[1].type = EDAC_MC_LAYER_CHANNEL;
- layers[1].size = 1;
- layers[1].is_virt_csrow = false;
- mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers,
- sizeof(*pdata));
- if (!mci) {
- devres_release_group(&op->dev, mpc85xx_mc_err_probe);
- return -ENOMEM;
- }
-
- pdata = mci->pvt_info;
- pdata->name = "mpc85xx_mc_err";
- pdata->irq = NO_IRQ;
- mci->pdev = &op->dev;
- pdata->edac_idx = edac_mc_idx++;
- dev_set_drvdata(mci->pdev, mci);
- mci->ctl_name = pdata->name;
- mci->dev_name = pdata->name;
-
- res = of_address_to_resource(op->dev.of_node, 0, &r);
- if (res) {
- pr_err("%s: Unable to get resource for MC err regs\n",
- __func__);
- goto err;
- }
-
- if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
- pdata->name)) {
- pr_err("%s: Error while requesting mem region\n",
- __func__);
- res = -EBUSY;
- goto err;
- }
-
- pdata->mc_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
- if (!pdata->mc_vbase) {
- pr_err("%s: Unable to setup MC err regs\n", __func__);
- res = -ENOMEM;
- goto err;
- }
-
- sdram_ctl = in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG);
- if (!(sdram_ctl & DSC_ECC_EN)) {
- /* no ECC */
- pr_warn("%s: No ECC DIMMs discovered\n", __func__);
- res = -ENODEV;
- goto err;
- }
-
- edac_dbg(3, "init mci\n");
- mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 |
- MEM_FLAG_DDR | MEM_FLAG_DDR2;
- mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
- mci->edac_cap = EDAC_FLAG_SECDED;
- mci->mod_name = EDAC_MOD_STR;
- mci->mod_ver = MPC85XX_REVISION;
-
- if (edac_op_state == EDAC_OPSTATE_POLL)
- mci->edac_check = mpc85xx_mc_check;
-
- mci->ctl_page_to_phys = NULL;
-
- mci->scrub_mode = SCRUB_SW_SRC;
-
- mpc85xx_init_csrows(mci);
-
- /* store the original error disable bits */
- orig_ddr_err_disable =
- in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE);
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE, 0);
-
- /* clear all error bits */
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0);
-
- if (edac_mc_add_mc_with_groups(mci, mpc85xx_dev_groups)) {
- edac_dbg(3, "failed edac_mc_add_mc()\n");
- goto err;
- }
-
- if (edac_op_state == EDAC_OPSTATE_INT) {
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN,
- DDR_EIE_MBEE | DDR_EIE_SBEE);
-
- /* store the original error management threshold */
- orig_ddr_err_sbe = in_be32(pdata->mc_vbase +
- MPC85XX_MC_ERR_SBE) & 0xff0000;
-
- /* set threshold to 1 error per interrupt */
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000);
-
- /* register interrupts */
- pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
- res = devm_request_irq(&op->dev, pdata->irq,
- mpc85xx_mc_isr,
- IRQF_SHARED,
- "[EDAC] MC err", mci);
- if (res < 0) {
- pr_err("%s: Unable to request irq %d for "
- "MPC85xx DRAM ERR\n", __func__, pdata->irq);
- irq_dispose_mapping(pdata->irq);
- res = -ENODEV;
- goto err2;
- }
-
- pr_info(EDAC_MOD_STR " acquired irq %d for MC\n",
- pdata->irq);
- }
-
- devres_remove_group(&op->dev, mpc85xx_mc_err_probe);
- edac_dbg(3, "success\n");
- pr_info(EDAC_MOD_STR " MC err registered\n");
-
- return 0;
-
-err2:
- edac_mc_del_mc(&op->dev);
-err:
- devres_release_group(&op->dev, mpc85xx_mc_err_probe);
- edac_mc_free(mci);
- return res;
-}
-
-static int mpc85xx_mc_err_remove(struct platform_device *op)
-{
- struct mem_ctl_info *mci = dev_get_drvdata(&op->dev);
- struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
-
- edac_dbg(0, "\n");
-
- if (edac_op_state == EDAC_OPSTATE_INT) {
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, 0);
- irq_dispose_mapping(pdata->irq);
- }
-
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE,
- orig_ddr_err_disable);
- out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe);
-
- edac_mc_del_mc(&op->dev);
- edac_mc_free(mci);
- return 0;
-}
-
static const struct of_device_id mpc85xx_mc_err_of_match[] = {
/* deprecate the fsl,85.. forms in the future, 2.6.30? */
{ .compatible = "fsl,8540-memory-controller", },
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h
index 9352e88..3f6fb16 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/mpc85xx_edac.h
@@ -17,65 +17,6 @@
#define mpc85xx_printk(level, fmt, arg...) \
edac_printk(level, "MPC85xx", fmt, ##arg)
-#define mpc85xx_mc_printk(mci, level, fmt, arg...) \
- edac_mc_chipset_printk(mci, level, "MPC85xx", fmt, ##arg)
-
-/*
- * DRAM error defines
- */
-
-/* DDR_SDRAM_CFG */
-#define MPC85XX_MC_DDR_SDRAM_CFG 0x0110
-#define MPC85XX_MC_CS_BNDS_0 0x0000
-#define MPC85XX_MC_CS_BNDS_1 0x0008
-#define MPC85XX_MC_CS_BNDS_2 0x0010
-#define MPC85XX_MC_CS_BNDS_3 0x0018
-#define MPC85XX_MC_CS_BNDS_OFS 0x0008
-
-#define MPC85XX_MC_DATA_ERR_INJECT_HI 0x0e00
-#define MPC85XX_MC_DATA_ERR_INJECT_LO 0x0e04
-#define MPC85XX_MC_ECC_ERR_INJECT 0x0e08
-#define MPC85XX_MC_CAPTURE_DATA_HI 0x0e20
-#define MPC85XX_MC_CAPTURE_DATA_LO 0x0e24
-#define MPC85XX_MC_CAPTURE_ECC 0x0e28
-#define MPC85XX_MC_ERR_DETECT 0x0e40
-#define MPC85XX_MC_ERR_DISABLE 0x0e44
-#define MPC85XX_MC_ERR_INT_EN 0x0e48
-#define MPC85XX_MC_CAPTURE_ATRIBUTES 0x0e4c
-#define MPC85XX_MC_CAPTURE_ADDRESS 0x0e50
-#define MPC85XX_MC_CAPTURE_EXT_ADDRESS 0x0e54
-#define MPC85XX_MC_ERR_SBE 0x0e58
-
-#define DSC_MEM_EN 0x80000000
-#define DSC_ECC_EN 0x20000000
-#define DSC_RD_EN 0x10000000
-#define DSC_DBW_MASK 0x00180000
-#define DSC_DBW_32 0x00080000
-#define DSC_DBW_64 0x00000000
-
-#define DSC_SDTYPE_MASK 0x07000000
-
-#define DSC_SDTYPE_DDR 0x02000000
-#define DSC_SDTYPE_DDR2 0x03000000
-#define DSC_SDTYPE_DDR3 0x07000000
-#define DSC_X32_EN 0x00000020
-
-/* Err_Int_En */
-#define DDR_EIE_MSEE 0x1 /* memory select */
-#define DDR_EIE_SBEE 0x4 /* single-bit ECC error */
-#define DDR_EIE_MBEE 0x8 /* multi-bit ECC error */
-
-/* Err_Detect */
-#define DDR_EDE_MSE 0x1 /* memory select */
-#define DDR_EDE_SBE 0x4 /* single-bit ECC error */
-#define DDR_EDE_MBE 0x8 /* multi-bit ECC error */
-#define DDR_EDE_MME 0x80000000 /* multiple memory errors */
-
-/* Err_Disable */
-#define DDR_EDI_MSED 0x1 /* memory select disable */
-#define DDR_EDI_SBED 0x4 /* single-bit ECC error disable */
-#define DDR_EDI_MBED 0x8 /* multi-bit ECC error disable */
-
/*
* L2 Err defines
*/
@@ -149,13 +90,6 @@
#define MPC85XX_PCIE_ERR_CAP_R2 0x0030
#define MPC85XX_PCIE_ERR_CAP_R3 0x0034
-struct mpc85xx_mc_pdata {
- char *name;
- int edac_idx;
- void __iomem *mc_vbase;
- int irq;
-};
-
struct mpc85xx_l2_pdata {
char *name;
int edac_idx;
--
2.7.4
next prev parent reply other threads:[~2016-08-09 21:57 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1470779760-16483-1-git-send-email-york.sun@nxp.com>
2016-08-09 21:55 ` [Patch v4 1/9] driver/edac/mpc85xx_edac: Drop setting/clearing RFXE bit in HID1 York Sun
2016-08-09 21:55 ` [Patch v4 2/9] driver/edac/mpc85xx_edac: Replace printk with proper pr_* format York Sun
2016-08-09 21:55 ` York Sun [this message]
2016-08-11 13:36 ` [Patch v4 3/9] driver/edac/fsl-ddr: Separate FSL DDR EDAC driver from MPC85xx Borislav Petkov
2016-08-11 15:05 ` york sun
2016-08-11 20:13 ` york sun
2016-08-09 21:55 ` [Patch v4 4/9] driver/edac/fsl_ddr: Rename macros and names York Sun
2016-08-09 21:55 ` [Patch v4 5/9] driver/edac/fsl_ddr: Add DDR types York Sun
2016-08-09 21:55 ` [Patch v4 6/9] driver/edac/fsl_ddr: Add support of little endian York Sun
2016-08-09 21:55 ` York Sun
2016-08-10 22:26 ` Rob Herring
2016-08-12 7:41 ` Borislav Petkov
2016-08-12 7:41 ` Borislav Petkov
2016-08-09 21:55 ` [Patch v4 7/9] driver/edac/fsl_ddr: Fix kernel warning when module is removed York Sun
2016-08-09 21:55 ` [Patch v4 8/9] driver/edac/layerscape_edac: Add Layerscape EDAC support York Sun
2016-08-09 21:55 ` York Sun
2016-08-12 9:12 ` Borislav Petkov
2016-08-12 9:12 ` Borislav Petkov
2016-08-23 16:46 ` york sun
2016-08-23 16:46 ` york sun
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1470779760-16483-4-git-send-email-york.sun@nxp.com \
--to=york.sun@nxp.com \
--cc=bp@alien8.de \
--cc=dougthompson@xmission.com \
--cc=linux-edac@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=morbidrsa@gmail.com \
--cc=oss@buserror.net \
--cc=stuart.yoder@nxp.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.