static int __devinit tile_edac_mc_probe(struct platform_device *pdev) { char hv_file[32]; int hv_devhdl; struct mem_ctl_info *mci; struct tile_edac_priv *priv; int rc; sprintf(hv_file, "mshim/%d", pdev->id); hv_devhdl = hv_dev_open((HV_VirtAddr)hv_file, 0); if (hv_devhdl < 0) { return -EINVAL; } /* A TILE MC has a single channel and one chip-select row. */ mci = edac_mc_alloc(sizeof(struct tile_edac_priv), TILE_EDAC_NR_CSROWS, TILE_EDAC_NR_CHANS, pdev->id); if (mci == NULL) return -ENOMEM; priv = mci->pvt_info; priv->node = pdev->id; priv->hv_devhdl = hv_devhdl; mci->dev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->mod_name = DRV_NAME; mci->ctl_name = "TILEPro_Memory_Controller"; mci->dev_name = dev_name(&pdev->dev); mci->edac_check = tile_edac_check; /* * Initialize the MC control structure 'csrows' table * with the mapping and control information. */ if (tile_edac_init_csrows(mci)) { /* No csrows found. */ mci->edac_cap = EDAC_FLAG_NONE; } else { mci->edac_cap = EDAC_FLAG_SECDED; } platform_set_drvdata(pdev, mci); /* Register with EDAC core */ rc = edac_mc_add_mc(mci); if (rc) { dev_err(&pdev->dev, "failed to register with EDAC core\n"); edac_mc_free(mci); return rc; } return 0; }
static int __devinit tile_edac_mc_probe(struct platform_device *pdev) { char hv_file[32]; int hv_devhdl; struct mem_ctl_info *mci; struct tile_edac_priv *priv; int rc; sprintf(hv_file, "mshim/%d", pdev->id); hv_devhdl = hv_dev_open((HV_VirtAddr)hv_file, 0); if (hv_devhdl < 0) return -EINVAL; mci = edac_mc_alloc(sizeof(struct tile_edac_priv), TILE_EDAC_NR_CSROWS, TILE_EDAC_NR_CHANS, pdev->id); if (mci == NULL) return -ENOMEM; priv = mci->pvt_info; priv->node = pdev->id; priv->hv_devhdl = hv_devhdl; mci->dev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->mod_name = DRV_NAME; #ifdef __tilegx__ mci->ctl_name = "TILEGx_Memory_Controller"; #else mci->ctl_name = "TILEPro_Memory_Controller"; #endif mci->dev_name = dev_name(&pdev->dev); mci->edac_check = tile_edac_check; if (tile_edac_init_csrows(mci)) { mci->edac_cap = EDAC_FLAG_NONE; } else { mci->edac_cap = EDAC_FLAG_SECDED; } platform_set_drvdata(pdev, mci); rc = edac_mc_add_mc(mci); if (rc) { dev_err(&pdev->dev, "failed to register with EDAC core\n"); edac_mc_free(mci); return rc; } return 0; }
static int r82600_probe1(struct pci_dev *pdev, int dev_idx) { struct mem_ctl_info *mci; u8 dramcr; u32 eapr; u32 scrub_disabled; u32 sdram_refresh_rate; struct r82600_error_info discard; debugf0("%s()\n", __func__); pci_read_config_byte(pdev, R82600_DRAMC, &dramcr); pci_read_config_dword(pdev, R82600_EAP, &eapr); scrub_disabled = eapr & BIT(31); sdram_refresh_rate = dramcr & (BIT(0) | BIT(1)); debugf2("%s(): sdram refresh rate = %#0x\n", __func__, sdram_refresh_rate); debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr); mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS, 0); if (mci == NULL) return -ENOMEM; debugf0("%s(): mci = %p\n", __func__, mci); mci->dev = &pdev->dev; mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; /* FIXME try to work out if the chip leads have been used for COM2 * instead on this board? [MA6?] MAYBE: */ /* On the R82600, the pins for memory bits 72:65 - i.e. the * * EC bits are shared with the pins for COM2 (!), so if COM2 * * is enabled, we assume COM2 is wired up, and thus no EDAC * * is possible. */ mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; if (ecc_enabled(dramcr)) { if (scrub_disabled) debugf3("%s(): mci = %p - Scrubbing disabled! EAP: " "%#0x\n", __func__, mci, eapr); } else mci->edac_cap = EDAC_FLAG_NONE; mci->mod_name = EDAC_MOD_STR; mci->mod_ver = R82600_REVISION; mci->ctl_name = "R82600"; mci->dev_name = pci_name(pdev); mci->edac_check = r82600_check; mci->ctl_page_to_phys = NULL; r82600_init_csrows(mci, pdev, dramcr); r82600_get_error_info(mci, &discard); /* clear counters */ /* Here we assume that we will never see multiple instances of this * type of memory controller. The ID is therefore hardcoded to 0. */ if (edac_mc_add_mc(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); goto fail; } /* get this far and it's successful */ if (disable_hardware_scrub) { debugf3("%s(): Disabling Hardware Scrub (scrub on error)\n", __func__); pci_write_bits32(pdev, R82600_EAP, BIT(31), BIT(31)); } /* allocating generic PCI control info */ r82600_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); if (!r82600_pci) { printk(KERN_WARNING "%s(): Unable to create PCI control\n", __func__); printk(KERN_WARNING "%s(): PCI error report via EDAC not setup\n", __func__); } debugf3("%s(): success\n", __func__); return 0; fail: edac_mc_free(mci); return -ENODEV; }
static int __devinit mpc85xx_mc_err_probe(struct of_device *op, const struct of_device_id *match) { struct mem_ctl_info *mci; 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; mci = edac_mc_alloc(sizeof(*pdata), 4, 1, edac_mc_idx); 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->dev = &op->dev; pdata->edac_idx = edac_mc_idx++; dev_set_drvdata(mci->dev, mci); mci->ctl_name = pdata->name; mci->dev_name = pdata->name; res = of_address_to_resource(op->node, 0, &r); if (res) { printk(KERN_ERR "%s: Unable to get resource for MC err regs\n", __func__); goto err; } if (!devm_request_mem_region(&op->dev, r.start, r.end - r.start + 1, pdata->name)) { printk(KERN_ERR "%s: Error while requesting mem region\n", __func__); res = -EBUSY; goto err; } pdata->mc_vbase = devm_ioremap(&op->dev, r.start, r.end - r.start + 1); if (!pdata->mc_vbase) { printk(KERN_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 */ printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__); res = -ENODEV; goto err; } debugf3("%s(): init mci\n", __func__); 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_set_mc_sysfs_attributes(mci); mpc85xx_init_csrows(mci); #ifdef CONFIG_EDAC_DEBUG edac_mc_register_mcidev_debug((struct attribute **)debug_attr); #endif /* 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(mci)) { debugf3("%s(): failed edac_mc_add_mc()\n", __func__); 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->node, 0); res = devm_request_irq(&op->dev, pdata->irq, mpc85xx_mc_isr, IRQF_DISABLED | IRQF_SHARED, "[EDAC] MC err", mci); if (res < 0) { printk(KERN_ERR "%s: Unable to request irq %d for " "MPC85xx DRAM ERR\n", __func__, pdata->irq); irq_dispose_mapping(pdata->irq); res = -ENODEV; goto err2; } printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC\n", pdata->irq); } devres_remove_group(&op->dev, mpc85xx_mc_err_probe); debugf3("%s(): success\n", __func__); printk(KERN_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 __devinit i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { int rc; struct mem_ctl_info *mci; struct i5100_priv *priv; struct pci_dev *ch0mm, *ch1mm; int ret = 0; u32 dw; int ranksperch; if (PCI_FUNC(pdev->devfn) != 1) return -ENODEV; rc = pci_enable_device(pdev); if (rc < 0) { ret = rc; goto bail; } /* ECC enabled? */ pci_read_config_dword(pdev, I5100_MC, &dw); if (!i5100_mc_errdeten(dw)) { printk(KERN_INFO "i5100_edac: ECC not enabled.\n"); ret = -ENODEV; goto bail_pdev; } /* figure out how many ranks, from strapped state of 48GB_Mode input */ pci_read_config_dword(pdev, I5100_MS, &dw); ranksperch = !!(dw & (1 << 8)) * 2 + 4; /* enable error reporting... */ pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw); dw &= ~I5100_FERR_NF_MEM_ANY_MASK; pci_write_config_dword(pdev, I5100_EMASK_MEM, dw); /* device 21, func 0, Channel 0 Memory Map, Error Flag/Mask, etc... */ ch0mm = pci_get_device_func(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_21, 0); if (!ch0mm) { ret = -ENODEV; goto bail_pdev; } rc = pci_enable_device(ch0mm); if (rc < 0) { ret = rc; goto bail_ch0; } /* device 22, func 0, Channel 1 Memory Map, Error Flag/Mask, etc... */ ch1mm = pci_get_device_func(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_22, 0); if (!ch1mm) { ret = -ENODEV; goto bail_disable_ch0; } rc = pci_enable_device(ch1mm); if (rc < 0) { ret = rc; goto bail_ch1; } mci = edac_mc_alloc(sizeof(*priv), ranksperch * 2, 1, 0); if (!mci) { ret = -ENOMEM; goto bail_disable_ch1; } mci->dev = &pdev->dev; priv = mci->pvt_info; priv->ranksperchan = ranksperch; priv->mc = pdev; priv->ch0mm = ch0mm; priv->ch1mm = ch1mm; INIT_DELAYED_WORK(&(priv->i5100_scrubbing), i5100_refresh_scrubbing); /* If scrubbing was already enabled by the bios, start maintaining it */ pci_read_config_dword(pdev, I5100_MC, &dw); if (i5100_mc_scrben(dw)) { priv->scrub_enable = 1; schedule_delayed_work(&(priv->i5100_scrubbing), I5100_SCRUB_REFRESH_RATE); } i5100_init_dimm_layout(pdev, mci); i5100_init_interleaving(pdev, mci); mci->mtype_cap = MEM_FLAG_FB_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = "i5100_edac.c"; mci->mod_ver = "not versioned"; mci->ctl_name = "i5100"; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; mci->edac_check = i5100_check_error; mci->set_sdram_scrub_rate = i5100_set_scrub_rate; mci->get_sdram_scrub_rate = i5100_get_scrub_rate; i5100_init_csrows(mci); /* this strange construction seems to be in every driver, dunno why */ switch (edac_op_state) { case EDAC_OPSTATE_POLL: case EDAC_OPSTATE_NMI: break; default: edac_op_state = EDAC_OPSTATE_POLL; break; } if (edac_mc_add_mc(mci)) { ret = -ENODEV; goto bail_scrub; } return ret; bail_scrub: priv->scrub_enable = 0; cancel_delayed_work_sync(&(priv->i5100_scrubbing)); edac_mc_free(mci); bail_disable_ch1: pci_disable_device(ch1mm); bail_ch1: pci_dev_put(ch1mm); bail_disable_ch0: pci_disable_device(ch0mm); bail_ch0: pci_dev_put(ch0mm); bail_pdev: pci_disable_device(pdev); bail: return ret; }
static int octeon_lmc_edac_probe(struct platform_device *pdev) { struct mem_ctl_info *mci; struct edac_mc_layer layers[1]; int mc = pdev->id; opstate_init(); layers[0].type = EDAC_MC_LAYER_CHANNEL; layers[0].size = 1; layers[0].is_virt_csrow = false; if (OCTEON_IS_MODEL(OCTEON_FAM_1_PLUS)) { union cvmx_lmcx_mem_cfg0 cfg0; cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); if (!cfg0.s.ecc_ena) { dev_info(&pdev->dev, "Disabled (ECC not enabled)\n"); return 0; } mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, sizeof(struct octeon_lmc_pvt)); if (!mci) return -ENXIO; mci->pdev = &pdev->dev; mci->dev_name = dev_name(&pdev->dev); mci->mod_name = "octeon-lmc"; mci->ctl_name = "octeon-lmc-err"; mci->edac_check = octeon_lmc_edac_poll; if (edac_mc_add_mc_with_groups(mci, octeon_dev_groups)) { dev_err(&pdev->dev, "edac_mc_add_mc() failed\n"); edac_mc_free(mci); return -ENXIO; } cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc)); cfg0.s.intr_ded_ena = 0; /* We poll */ cfg0.s.intr_sec_ena = 0; cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), cfg0.u64); } else { /* OCTEON II */ union cvmx_lmcx_int_en en; union cvmx_lmcx_config config; config.u64 = cvmx_read_csr(CVMX_LMCX_CONFIG(0)); if (!config.s.ecc_ena) { dev_info(&pdev->dev, "Disabled (ECC not enabled)\n"); return 0; } mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, sizeof(struct octeon_lmc_pvt)); if (!mci) return -ENXIO; mci->pdev = &pdev->dev; mci->dev_name = dev_name(&pdev->dev); mci->mod_name = "octeon-lmc"; mci->ctl_name = "co_lmc_err"; mci->edac_check = octeon_lmc_edac_poll_o2; if (edac_mc_add_mc_with_groups(mci, octeon_dev_groups)) { dev_err(&pdev->dev, "edac_mc_add_mc() failed\n"); edac_mc_free(mci); return -ENXIO; } en.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc)); en.s.intr_ded_ena = 0; /* We poll */ en.s.intr_sec_ena = 0; cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), en.u64); } platform_set_drvdata(pdev, mci); return 0; }
static int __devinit i5100_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { int rc; struct mem_ctl_info *mci; struct i5100_priv *priv; struct pci_dev *ch0mm, *ch1mm; int ret = 0; u32 dw; int ranksperch; if (PCI_FUNC(pdev->devfn) != 1) return -ENODEV; rc = pci_enable_device(pdev); if (rc < 0) { ret = rc; goto bail; } /* ECC enabled? */ pci_read_config_dword(pdev, I5100_MC, &dw); if (!i5100_mc_errdeten(dw)) { printk(KERN_INFO "i5100_edac: ECC not enabled.\n"); ret = -ENODEV; goto bail_pdev; } /* figure out how many ranks, from strapped state of 48GB_Mode input */ pci_read_config_dword(pdev, I5100_MS, &dw); ranksperch = !!(dw & (1 << 8)) * 2 + 4; if (ranksperch != 4) { /* FIXME: get 6 ranks / controller to work - need hw... */ printk(KERN_INFO "i5100_edac: unsupported configuration.\n"); ret = -ENODEV; goto bail_pdev; } /* enable error reporting... */ pci_read_config_dword(pdev, I5100_EMASK_MEM, &dw); dw &= ~I5100_FERR_NF_MEM_ANY_MASK; pci_write_config_dword(pdev, I5100_EMASK_MEM, dw); /* device 21, func 0, Channel 0 Memory Map, Error Flag/Mask, etc... */ ch0mm = pci_get_device_func(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_21, 0); if (!ch0mm) { ret = -ENODEV; goto bail_pdev; } rc = pci_enable_device(ch0mm); if (rc < 0) { ret = rc; goto bail_ch0; } /* device 22, func 0, Channel 1 Memory Map, Error Flag/Mask, etc... */ ch1mm = pci_get_device_func(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5100_22, 0); if (!ch1mm) { ret = -ENODEV; goto bail_disable_ch0; } rc = pci_enable_device(ch1mm); if (rc < 0) { ret = rc; goto bail_ch1; } mci = edac_mc_alloc(sizeof(*priv), ranksperch * 2, 1, 0); if (!mci) { ret = -ENOMEM; goto bail_disable_ch1; } mci->dev = &pdev->dev; priv = mci->pvt_info; priv->ranksperctlr = ranksperch; priv->mc = pdev; priv->ch0mm = ch0mm; priv->ch1mm = ch1mm; i5100_init_dimm_layout(pdev, mci); i5100_init_interleaving(pdev, mci); mci->mtype_cap = MEM_FLAG_FB_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = "i5100_edac.c"; mci->mod_ver = "not versioned"; mci->ctl_name = "i5100"; mci->dev_name = pci_name(pdev); mci->ctl_page_to_phys = NULL; mci->edac_check = i5100_check_error; i5100_init_csrows(mci); /* this strange construction seems to be in every driver, dunno why */ switch (edac_op_state) { case EDAC_OPSTATE_POLL: case EDAC_OPSTATE_NMI: break; default: edac_op_state = EDAC_OPSTATE_POLL; break; } if (edac_mc_add_mc(mci)) { ret = -ENODEV; goto bail_mc; } return ret; bail_mc: edac_mc_free(mci); bail_disable_ch1: pci_disable_device(ch1mm); bail_ch1: pci_dev_put(ch1mm); bail_disable_ch0: pci_disable_device(ch0mm); bail_ch0: pci_dev_put(ch0mm); bail_pdev: pci_disable_device(pdev); bail: return ret; }
static int tile_edac_mc_probe(struct platform_device *pdev) { char hv_file[32]; int hv_devhdl; struct mem_ctl_info *mci; struct edac_mc_layer layers[2]; struct tile_edac_priv *priv; int rc; sprintf(hv_file, "mshim/%d", pdev->id); hv_devhdl = hv_dev_open((HV_VirtAddr)hv_file, 0); if (hv_devhdl < 0) return -EINVAL; /* A TILE MC has a single channel and one chip-select row. */ layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; layers[0].size = TILE_EDAC_NR_CSROWS; layers[0].is_virt_csrow = true; layers[1].type = EDAC_MC_LAYER_CHANNEL; layers[1].size = TILE_EDAC_NR_CHANS; layers[1].is_virt_csrow = false; mci = edac_mc_alloc(pdev->id, ARRAY_SIZE(layers), layers, sizeof(struct tile_edac_priv)); if (mci == NULL) return -ENOMEM; priv = mci->pvt_info; priv->node = pdev->id; priv->hv_devhdl = hv_devhdl; mci->pdev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->mod_name = DRV_NAME; #ifdef __tilegx__ mci->ctl_name = "TILEGx_Memory_Controller"; #else mci->ctl_name = "TILEPro_Memory_Controller"; #endif mci->dev_name = dev_name(&pdev->dev); mci->edac_check = tile_edac_check; /* * Initialize the MC control structure 'csrows' table * with the mapping and control information. */ if (tile_edac_init_csrows(mci)) { /* No csrows found. */ mci->edac_cap = EDAC_FLAG_NONE; } else { mci->edac_cap = EDAC_FLAG_SECDED; } platform_set_drvdata(pdev, mci); /* Register with EDAC core */ rc = edac_mc_add_mc(mci); if (rc) { dev_err(&pdev->dev, "failed to register with EDAC core\n"); edac_mc_free(mci); return rc; } return 0; }
static int __devinit pasemi_edac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mem_ctl_info *mci = NULL; u32 errctl1, errcor, scrub, mcen; pci_read_config_dword(pdev, MCCFG_MCEN, &mcen); if (!(mcen & MCCFG_MCEN_MMC_EN)) return -ENODEV; /* * We should think about enabling other error detection later on */ pci_read_config_dword(pdev, MCDEBUG_ERRCTL1, &errctl1); errctl1 |= MCDEBUG_ERRCTL1_SBE_LOG_EN | MCDEBUG_ERRCTL1_MBE_LOG_EN | MCDEBUG_ERRCTL1_RFL_LOG_EN; pci_write_config_dword(pdev, MCDEBUG_ERRCTL1, errctl1); mci = edac_mc_alloc(0, PASEMI_EDAC_NR_CSROWS, PASEMI_EDAC_NR_CHANS, system_mmc_id++); if (mci == NULL) return -ENOMEM; pci_read_config_dword(pdev, MCCFG_ERRCOR, &errcor); errcor |= MCCFG_ERRCOR_RNK_FAIL_DET_EN | MCCFG_ERRCOR_ECC_GEN_EN | MCCFG_ERRCOR_ECC_CRR_EN; mci->dev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR; mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->edac_cap = (errcor & MCCFG_ERRCOR_ECC_GEN_EN) ? ((errcor & MCCFG_ERRCOR_ECC_CRR_EN) ? (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_EC) : EDAC_FLAG_NONE; mci->mod_name = MODULE_NAME; mci->dev_name = pci_name(pdev); mci->ctl_name = "pasemi,pwrficient-mc"; mci->edac_check = pasemi_edac_check; mci->ctl_page_to_phys = NULL; pci_read_config_dword(pdev, MCCFG_SCRUB, &scrub); mci->scrub_cap = SCRUB_FLAG_HW_PROG | SCRUB_FLAG_HW_SRC; mci->scrub_mode = ((errcor & MCCFG_ERRCOR_ECC_CRR_EN) ? SCRUB_FLAG_HW_SRC : 0) | ((scrub & MCCFG_SCRUB_RGLR_SCRB_EN) ? SCRUB_FLAG_HW_PROG : 0); if (pasemi_edac_init_csrows(mci, pdev, (mci->edac_cap & EDAC_FLAG_SECDED) ? EDAC_SECDED : ((mci->edac_cap & EDAC_FLAG_EC) ? EDAC_EC : EDAC_NONE))) goto fail; /* * Clear status */ pasemi_edac_get_error_info(mci); if (edac_mc_add_mc(mci)) goto fail; /* get this far and it's successful */ return 0; fail: edac_mc_free(mci); return -ENODEV; }
static int i3000_probe1(struct pci_dev *pdev, int dev_idx) { int rc; int i; struct mem_ctl_info *mci = NULL; unsigned long last_cumul_size; int interleaved, nr_channels; unsigned char dra[I3000_RANKS / 2], drb[I3000_RANKS]; unsigned char *c0dra = dra, *c1dra = &dra[I3000_RANKS_PER_CHANNEL / 2]; unsigned char *c0drb = drb, *c1drb = &drb[I3000_RANKS_PER_CHANNEL]; unsigned long mchbar; void __iomem *window; debugf0("MC: %s()\n", __func__); pci_read_config_dword(pdev, I3000_MCHBAR, (u32 *) & mchbar); mchbar &= I3000_MCHBAR_MASK; window = ioremap_nocache(mchbar, I3000_MMR_WINDOW_SIZE); if (!window) { printk(KERN_ERR "i3000: cannot map mmio space at 0x%lx\n", mchbar); return -ENODEV; } c0dra[0] = readb(window + I3000_C0DRA + 0); /* ranks 0,1 */ c0dra[1] = readb(window + I3000_C0DRA + 1); /* ranks 2,3 */ c1dra[0] = readb(window + I3000_C1DRA + 0); /* ranks 0,1 */ c1dra[1] = readb(window + I3000_C1DRA + 1); /* ranks 2,3 */ for (i = 0; i < I3000_RANKS_PER_CHANNEL; i++) { c0drb[i] = readb(window + I3000_C0DRB + i); c1drb[i] = readb(window + I3000_C1DRB + i); } iounmap(window); /* Figure out how many channels we have. * * If we have what the datasheet calls "asymmetric channels" * (essentially the same as what was called "virtual single * channel mode" in the i82875) then it's a single channel as * far as EDAC is concerned. */ interleaved = i3000_is_interleaved(c0dra, c1dra, c0drb, c1drb); nr_channels = interleaved ? 2 : 1; mci = edac_mc_alloc(0, I3000_RANKS / nr_channels, nr_channels, 0); if (!mci) return -ENOMEM; debugf3("MC: %s(): init mci\n", __func__); mci->dev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR2; mci->edac_ctl_cap = EDAC_FLAG_SECDED; mci->edac_cap = EDAC_FLAG_SECDED; mci->mod_name = EDAC_MOD_STR; mci->mod_ver = I3000_REVISION; mci->ctl_name = i3000_devs[dev_idx].ctl_name; mci->dev_name = pci_name(pdev); mci->edac_check = i3000_check; mci->ctl_page_to_phys = NULL; /* * The dram rank boundary (DRB) reg values are boundary addresses * for each DRAM rank with a granularity of 32MB. DRB regs are * cumulative; the last one will contain the total memory * contained in all ranks. * * If we're in interleaved mode then we're only walking through * the ranks of controller 0, so we double all the values we see. */ for (last_cumul_size = i = 0; i < mci->nr_csrows; i++) { u8 value; u32 cumul_size; struct csrow_info *csrow = &mci->csrows[i]; value = drb[i]; cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT); if (interleaved) cumul_size <<= 1; debugf3("MC: %s(): (%d) cumul_size 0x%x\n", __func__, i, cumul_size); if (cumul_size == last_cumul_size) { csrow->mtype = MEM_EMPTY; continue; } csrow->first_page = last_cumul_size; csrow->last_page = cumul_size - 1; csrow->nr_pages = cumul_size - last_cumul_size; last_cumul_size = cumul_size; csrow->grain = I3000_DEAP_GRAIN; csrow->mtype = MEM_DDR2; csrow->dtype = DEV_UNKNOWN; csrow->edac_mode = EDAC_UNKNOWN; } /* Clear any error bits. * (Yes, we really clear bits by writing 1 to them.) */ pci_write_bits16(pdev, I3000_ERRSTS, I3000_ERRSTS_BITS, I3000_ERRSTS_BITS); rc = -ENODEV; if (edac_mc_add_mc(mci)) { debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); goto fail; } /* allocating generic PCI control info */ i3000_pci = edac_pci_create_generic_ctl(&pdev->dev, EDAC_MOD_STR); if (!i3000_pci) { printk(KERN_WARNING "%s(): Unable to create PCI control\n", __func__); printk(KERN_WARNING "%s(): PCI error report via EDAC not setup\n", __func__); } /* get this far and it's successful */ debugf3("MC: %s(): success\n", __func__); return 0; fail: if (mci) edac_mc_free(mci); return rc; }