I've verified this patch can apply for galak/powerpc.git 'next' branch with no 
change.


Best Regards, 
Shaohui Xie 


>-----Original Message-----
>From: Xie Shaohui-B21989
>Sent: Thursday, July 21, 2011 6:33 PM
>To: linuxppc-dev@lists.ozlabs.org
>Cc: Gala Kumar-B11780; mm-comm...@vger.kernel.org; avoront...@mvista.com;
>da...@davemloft.net; grant.lik...@secretlab.ca; a...@linux-foundation.org;
>Jiang Kai-B18973; Kumar Gala; Xie Shaohui-B21989
>Subject: [PATCH 4/4] edac/85xx: PCI/PCIE error interrupt edac support.
>
>From: Kai.Jiang <kai.ji...@freescale.com>
>
>Add pcie error interrupt edac support for mpc85xx and p4080.
>mpc85xx uses the legacy interrupt report mechanism - the error interrupts
>are reported directly to mpic. While, p4080 attaches most of error
>interrupts to interrupt 0. And report error interrupt to mpic via
>interrupt 0. This patch can handle both of them.
>
>
>Due to the error management register offset and definition
>
>difference between pci and pcie, use ccsr_pci structure to merge pci and
>pcie edac code into one.
>
>Signed-off-by: Kai.Jiang <kai.ji...@freescale.com>
>Signed-off-by: Kumar Gala <ga...@kernel.crashing.org>
>Signed-off-by: Shaohui Xie <shaohui....@freescale.com>
>---
> drivers/edac/mpc85xx_edac.c |  239 ++++++++++++++++++++++++++++++++------
>----
> drivers/edac/mpc85xx_edac.h |   17 +--
> 2 files changed, 188 insertions(+), 68 deletions(-)
>
>diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
>index b048a5f..dde156f 100644
>--- a/drivers/edac/mpc85xx_edac.c
>+++ b/drivers/edac/mpc85xx_edac.c
>@@ -1,5 +1,6 @@
> /*
>  * Freescale MPC85xx Memory Controller kenel module
>+ * Copyright (c) 2011 Freescale Semiconductor, Inc.
>  *
>  * Author: Dave Jiang <dji...@mvista.com>
>  *
>@@ -21,6 +22,8 @@
>
> #include <linux/of_platform.h>
> #include <linux/of_device.h>
>+#include <include/asm/pci.h>
>+#include <sysdev/fsl_pci.h>
> #include "edac_module.h"
> #include "edac_core.h"
> #include "mpc85xx_edac.h"
>@@ -34,14 +37,6 @@ 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;
> #ifdef CONFIG_FSL_SOC_BOOKE
> static u32 orig_hid1[2];
>@@ -151,37 +146,52 @@ static void mpc85xx_pci_check(struct
>edac_pci_ctl_info *pci)  {
>       struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
>       u32 err_detect;
>+      struct ccsr_pci *reg = pdata->pci_reg;
>+
>+      err_detect = in_be32(&pdata->pci_reg->pex_err_dr);
>+
>+      if (pdata->pcie_flag) {
>+              printk(KERN_ERR "PCIE error(s) detected\n");
>+              printk(KERN_ERR "PCIE ERR_DR register: 0x%08x\n", err_detect);
>+              printk(KERN_ERR "PCIE ERR_CAP_STAT register: 0x%08x\n",
>+                      in_be32(&reg->pex_err_cap_stat));
>+              printk(KERN_ERR "PCIE ERR_CAP_R0 register: 0x%08x\n",
>+                      in_be32(&reg->pex_err_cap_r0));
>+              printk(KERN_ERR "PCIE ERR_CAP_R1 register: 0x%08x\n",
>+                      in_be32(&reg->pex_err_cap_r1));
>+              printk(KERN_ERR "PCIE ERR_CAP_R2 register: 0x%08x\n",
>+                      in_be32(&reg->pex_err_cap_r2));
>+              printk(KERN_ERR "PCIE ERR_CAP_R3 register: 0x%08x\n",
>+                      in_be32(&reg->pex_err_cap_r3));
>+      } else {
>+              /* master aborts can happen during PCI config cycles */
>+              if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
>+                      out_be32(&reg->pex_err_dr, err_detect);
>+                      return;
>+              }
>
>-      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;
>+              printk(KERN_ERR "PCI error(s) detected\n");
>+              printk(KERN_ERR "PCI/X ERR_DR register: 0x%08x\n", err_detect);
>+              printk(KERN_ERR "PCI/X ERR_ATTRIB register: 0x%08x\n",
>+                     in_be32(&reg->pex_err_attrib));
>+              printk(KERN_ERR "PCI/X ERR_ADDR register: 0x%08x\n",
>+                     in_be32(&reg->pex_err_disr));
>+              printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: 0x%08x\n",
>+                     in_be32(&reg->pex_err_ext_addr));
>+              printk(KERN_ERR "PCI/X ERR_DL register: 0x%08x\n",
>+                     in_be32(&reg->pex_err_dl));
>+              printk(KERN_ERR "PCI/X ERR_DH register: 0x%08x\n",
>+                     in_be32(&reg->pex_err_dh));
>+
>+              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);
>       }
>
>-      printk(KERN_ERR "PCI error(s) detected\n");
>-      printk(KERN_ERR "PCI/X ERR_DR register: %#08x\n", err_detect);
>-
>-      printk(KERN_ERR "PCI/X ERR_ATTRIB register: %#08x\n",
>-             in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
>-      printk(KERN_ERR "PCI/X ERR_ADDR register: %#08x\n",
>-             in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
>-      printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: %#08x\n",
>-             in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
>-      printk(KERN_ERR "PCI/X ERR_DL register: %#08x\n",
>-             in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
>-      printk(KERN_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);
>+      out_be32(&reg->pex_err_dr, err_detect);
> }
>
> static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) @@ -190,7
>+200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
>       struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
>       u32 err_detect;
>
>-      err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
>+      err_detect = in_be32(&pdata->pci_reg->pex_err_dr);
>
>       if (!err_detect)
>               return IRQ_NONE;
>@@ -200,11 +210,99 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void
>*dev_id)
>       return IRQ_HANDLED;
> }
>
>+#define MPC85XX_MPIC_EIMR0    0x3910
>+/*
>+ * This function is for error interrupt ORed mechanism.
>+ * This mechanism attaches most functions' error interrupts to interrupt
>0.
>+ * And report error interrupt to mpic via interrupt 0.
>+ * EIMR0 - Error Interrupt Mask Register 0.
>+ *
>+ * This function check whether the device support error interrupt ORed
>+ * mechanism via device tree. If supported, umask pcie error interrupt
>+ * bit in EIMR0.
>+ */
>+static int mpc85xx_err_int_en(struct device *op) {
>+      u32 *int_cell = NULL;
>+      struct device_node *np = NULL;
>+      void __iomem *mpic_base = NULL;
>+      u32 reg_tmp = 0;
>+      u32 int_len = 0;
>+      struct resource r;
>+      int res = 0;
>+
>+      if (!op->of_node)
>+              return -EINVAL;
>+      /*
>+       * Unmask pcie error interrupt bit in EIMR0
>+       * extend interrupt specifier has 4 cells. For the 3rd cell:
>+       * 0 -- normal interrupt; 1 -- error interrupt.
>+       */
>+      int_cell = (u32 *)of_get_property(op->of_node, "interrupts",
>&int_len);
>+      if ((int_len/sizeof(u32)) == 4) {
>+              /* soc has error interrupt integration handling mechanism */
>+              if (*(int_cell + 2) == 1) {
>+                      np = of_find_node_by_type(NULL, "open-pic");
>+
>+                      if (of_address_to_resource(np, 0, &r)) {
>+                              printk(KERN_ERR
>+                              "%s:Failed to map mpic regs\n", __func__);
>+                              of_node_put(np);
>+                              res = -ENOMEM;
>+                              goto err;
>+                      }
>+
>+                      if (!request_mem_region(r.start,
>+                                              r.end - r.start + 1, "mpic")) {
>+                              printk(KERN_ERR
>+                              "%s:Error while requesting mem region\n",
>+                                       __func__);
>+                              res = -EBUSY;
>+                              goto err;
>+                      }
>+
>+                      mpic_base = ioremap(r.start, r.end - r.start + 1);
>+                      if (!mpic_base) {
>+                              printk(KERN_ERR
>+                              "%s:Unable to map mpic regs\n", __func__);
>+                              res = -ENOMEM;
>+                              goto err_ioremap;
>+                      }
>+
>+                      reg_tmp = in_be32(mpic_base + MPC85XX_MPIC_EIMR0);
>+                      out_be32(mpic_base + MPC85XX_MPIC_EIMR0,
>+                              reg_tmp & ~(1 << (31 - *(int_cell + 3))));
>+                      iounmap(mpic_base);
>+                      release_mem_region(r.start, r.end - r.start + 1);
>+                      of_node_put(np);
>+              }
>+      }
>+
>+      return 0;
>+err_ioremap:
>+      release_mem_region(r.start, r.end - r.start + 1);
>+err:
>+
>+      return res;
>+}
>+
>+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, hose->bus->number,
>+                                   0, PCI_CAP_ID_EXP);
>+}
>+
> static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)  {
>       struct edac_pci_ctl_info *pci;
>       struct mpc85xx_pci_pdata *pdata;
>       struct resource r;
>+      struct ccsr_pci *reg = NULL;
>       int res = 0;
>
>       if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
>@@ -217,6 +315,10 @@ static int __devinit mpc85xx_pci_err_probe(struct
>platform_device *op)
>       pdata = pci->pvt_info;
>       pdata->name = "mpc85xx_pci_err";
>       pdata->irq = NO_IRQ;
>+
>+      if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0)
>+              pdata->pcie_flag = 1;
>+
>       dev_set_drvdata(&op->dev, pci);
>       pci->dev = &op->dev;
>       pci->mod_name = EDAC_MOD_STR;
>@@ -235,37 +337,40 @@ static int __devinit mpc85xx_pci_err_probe(struct
>platform_device *op)
>               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)) {
>-              printk(KERN_ERR "%s: Error while requesting mem region\n",
>-                     __func__);
>+              printk(KERN_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) {
>+      pdata->pci_reg = devm_ioremap(&op->dev, r.start, resource_size(&r));
>+      if (!pdata->pci_reg) {
>               printk(KERN_ERR "%s: Unable to setup PCI err regs\n",
>__func__);
>               res = -ENOMEM;
>               goto err;
>       }
>
>-      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);
>+      if (mpc85xx_err_int_en(&op->dev) < 0)
>+              goto err;
>
>-      orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
>+      reg = pdata->pci_reg;
>+      /* disable pci/pcie error detect */
>+      if (pdata->pcie_flag) {
>+              pdata->orig_pci_err_dr =  in_be32(&reg->pex_err_disr);
>+              out_be32(&reg->pex_err_disr, ~0);
>+      } else {
>+              pdata->orig_pci_err_dr =  in_be32(&reg->pex_err_cap_dr);
>+              out_be32(&reg->pex_err_cap_dr, ~0);
>+      }
>
>-      /* disable master abort reporting */
>-      out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
>+      /* disable all pcie error interrupt */
>+      pdata->orig_pci_err_en = in_be32(&reg->pex_err_en);
>+      out_be32(&reg->pex_err_en, 0);
>
>-      /* clear error bits */
>-      out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
>+      /* clear all error bits */
>+      out_be32(&reg->pex_err_dr, ~0);
>
>       if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
>               debugf3("%s(): failed edac_pci_add_device()\n", __func__); @@
>-275,7 +380,7 @@ static int __devinit mpc85xx_pci_err_probe(struct
>platform_device *op)
>       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_pci_isr, IRQF_DISABLED,
>+                                     mpc85xx_pci_isr, IRQF_SHARED,
>                                      "[EDAC] PCI err", pci);
>               if (res < 0) {
>                       printk(KERN_ERR
>@@ -290,6 +395,17 @@ static int __devinit mpc85xx_pci_err_probe(struct
>platform_device *op)
>                      pdata->irq);
>       }
>
>+      if (pdata->pcie_flag) {
>+              /* enable all pcie error interrupt & error detect */
>+              out_be32(&reg->pex_err_en, ~0);
>+              out_be32(&reg->pex_err_disr, 0);
>+      } else {
>+              /* PCI master abort is expected during config cycles */
>+              out_be32(&reg->pex_err_cap_dr, PCI_ERR_CAP_DR_DIS_MST);
>+              /* disable master abort reporting */
>+              out_be32(&reg->pex_err_en, PCI_ERR_EN_DIS_MST);
>+      }
>+
>       devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
>       debugf3("%s(): success\n", __func__);
>       printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); @@ -311,10
>+427,13 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
>
>       debugf0("%s()\n", __func__);
>
>-      out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR,
>-               orig_pci_err_cap_dr);
>+      if (pdata->pcie_flag)
>+              out_be32(&pdata->pci_reg->pex_err_disr, pdata-
>>orig_pci_err_dr);
>+      else
>+              out_be32(&pdata->pci_reg->pex_err_cap_dr,
>+                                      pdata->orig_pci_err_dr);
>
>-      out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);
>+      out_be32(&pdata->pci_reg->pex_err_en, pdata->orig_pci_err_en);
>
>       edac_pci_del_device(pci->dev);
>
>@@ -333,6 +452,12 @@ static struct of_device_id mpc85xx_pci_err_of_match[]
>= {
>       {
>        .compatible = "fsl,mpc8540-pci",
>       },
>+      {
>+       .compatible = "fsl,mpc8548-pcie",
>+      },
>+      {
>+       .compatible = "fsl,p4080-pcie",
>+      },
>       {},
> };
> MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match); diff --git
>a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h index
>932016f..d0e7b11 100644
>--- a/drivers/edac/mpc85xx_edac.h
>+++ b/drivers/edac/mpc85xx_edac.h
>@@ -131,16 +131,8 @@
> #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 MPC85XX_PCI_ERR_ATTRIB                0x000c
>-#define MPC85XX_PCI_ERR_ADDR          0x0010
>-#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 PCI_ERR_CAP_DR_DIS_MST         0x40
>+#define PCI_ERR_EN_DIS_MST             (~0x40)
>
> struct mpc85xx_mc_pdata {
>       char *name;
>@@ -159,8 +151,11 @@ struct mpc85xx_l2_pdata {  struct mpc85xx_pci_pdata {
>       char *name;
>       int edac_idx;
>-      void __iomem *pci_vbase;
>       int irq;
>+      struct ccsr_pci *pci_reg;
>+      u8 pcie_flag;
>+      u32 orig_pci_err_dr;
>+      u32 orig_pci_err_en;
> };
>
> #endif
>--
>1.6.4


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to