in cpc925_edac.c [906:1011]
static int cpc925_probe(struct platform_device *pdev)
{
static int edac_mc_idx;
struct mem_ctl_info *mci;
struct edac_mc_layer layers[2];
void __iomem *vbase;
struct cpc925_mc_pdata *pdata;
struct resource *r;
int res = 0, nr_channels;
edac_dbg(0, "%s platform device found!\n", pdev->name);
if (!devres_open_group(&pdev->dev, cpc925_probe, GFP_KERNEL)) {
res = -ENOMEM;
goto out;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
cpc925_printk(KERN_ERR, "Unable to get resource\n");
res = -ENOENT;
goto err1;
}
if (!devm_request_mem_region(&pdev->dev,
r->start,
resource_size(r),
pdev->name)) {
cpc925_printk(KERN_ERR, "Unable to request mem region\n");
res = -EBUSY;
goto err1;
}
vbase = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (!vbase) {
cpc925_printk(KERN_ERR, "Unable to ioremap device\n");
res = -ENOMEM;
goto err2;
}
nr_channels = cpc925_mc_get_channels(vbase) + 1;
layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
layers[0].size = CPC925_NR_CSROWS;
layers[0].is_virt_csrow = true;
layers[1].type = EDAC_MC_LAYER_CHANNEL;
layers[1].size = nr_channels;
layers[1].is_virt_csrow = false;
mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers,
sizeof(struct cpc925_mc_pdata));
if (!mci) {
cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
res = -ENOMEM;
goto err2;
}
pdata = mci->pvt_info;
pdata->vbase = vbase;
pdata->edac_idx = edac_mc_idx++;
pdata->name = pdev->name;
mci->pdev = &pdev->dev;
platform_set_drvdata(pdev, mci);
mci->dev_name = dev_name(&pdev->dev);
mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
mci->mod_name = CPC925_EDAC_MOD_STR;
mci->ctl_name = pdev->name;
if (edac_op_state == EDAC_OPSTATE_POLL)
mci->edac_check = cpc925_mc_check;
mci->ctl_page_to_phys = NULL;
mci->scrub_mode = SCRUB_SW_SRC;
mci->set_sdram_scrub_rate = NULL;
mci->get_sdram_scrub_rate = cpc925_get_sdram_scrub_rate;
cpc925_init_csrows(mci);
/* Setup memory controller registers */
cpc925_mc_init(mci);
if (edac_mc_add_mc(mci) > 0) {
cpc925_mc_printk(mci, KERN_ERR, "Failed edac_mc_add_mc()\n");
goto err3;
}
cpc925_add_edac_devices(vbase);
/* get this far and it's successful */
edac_dbg(0, "success\n");
res = 0;
goto out;
err3:
cpc925_mc_exit(mci);
edac_mc_free(mci);
err2:
devm_release_mem_region(&pdev->dev, r->start, resource_size(r));
err1:
devres_release_group(&pdev->dev, cpc925_probe);
out:
return res;
}