in altera_edac.c [1855:1992]
static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
struct device_node *np)
{
struct edac_device_ctl_info *dci;
struct altr_edac_device_dev *altdev;
char *ecc_name = (char *)np->name;
struct resource res;
int edac_idx;
int rc = 0;
const struct edac_device_prv_data *prv;
/* Get matching node and check for valid result */
const struct of_device_id *pdev_id =
of_match_node(altr_edac_a10_device_of_match, np);
if (IS_ERR_OR_NULL(pdev_id))
return -ENODEV;
/* Get driver specific data for this EDAC device */
prv = pdev_id->data;
if (IS_ERR_OR_NULL(prv))
return -ENODEV;
if (validate_parent_available(np))
return -ENODEV;
if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL))
return -ENOMEM;
if (of_device_is_compatible(np, "altr,sdram-edac-s10"))
rc = get_s10_sdram_edac_resource(np, &res);
else
rc = of_address_to_resource(np, 0, &res);
if (rc < 0) {
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s: no resource address\n", ecc_name);
goto err_release_group;
}
edac_idx = edac_device_alloc_index();
dci = edac_device_alloc_ctl_info(sizeof(*altdev), ecc_name,
1, ecc_name, 1, 0, NULL, 0,
edac_idx);
if (!dci) {
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s: Unable to allocate EDAC device\n", ecc_name);
rc = -ENOMEM;
goto err_release_group;
}
altdev = dci->pvt_info;
dci->dev = edac->dev;
altdev->edac_dev_name = ecc_name;
altdev->edac_idx = edac_idx;
altdev->edac = edac;
altdev->edac_dev = dci;
altdev->data = prv;
altdev->ddev = *edac->dev;
dci->dev = &altdev->ddev;
dci->ctl_name = "Altera ECC Manager";
dci->mod_name = ecc_name;
dci->dev_name = ecc_name;
altdev->base = devm_ioremap_resource(edac->dev, &res);
if (IS_ERR(altdev->base)) {
rc = PTR_ERR(altdev->base);
goto err_release_group1;
}
/* Check specific dependencies for the module */
if (altdev->data->setup) {
rc = altdev->data->setup(altdev);
if (rc)
goto err_release_group1;
}
altdev->sb_irq = irq_of_parse_and_map(np, 0);
if (!altdev->sb_irq) {
edac_printk(KERN_ERR, EDAC_DEVICE, "Error allocating SBIRQ\n");
rc = -ENODEV;
goto err_release_group1;
}
rc = devm_request_irq(edac->dev, altdev->sb_irq, prv->ecc_irq_handler,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
ecc_name, altdev);
if (rc) {
edac_printk(KERN_ERR, EDAC_DEVICE, "No SBERR IRQ resource\n");
goto err_release_group1;
}
#ifdef CONFIG_64BIT
/* Use IRQ to determine SError origin instead of assigning IRQ */
rc = of_property_read_u32_index(np, "interrupts", 0, &altdev->db_irq);
if (rc) {
edac_printk(KERN_ERR, EDAC_DEVICE,
"Unable to parse DB IRQ index\n");
goto err_release_group1;
}
#else
altdev->db_irq = irq_of_parse_and_map(np, 1);
if (!altdev->db_irq) {
edac_printk(KERN_ERR, EDAC_DEVICE, "Error allocating DBIRQ\n");
rc = -ENODEV;
goto err_release_group1;
}
rc = devm_request_irq(edac->dev, altdev->db_irq, prv->ecc_irq_handler,
IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
ecc_name, altdev);
if (rc) {
edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n");
goto err_release_group1;
}
#endif
rc = edac_device_add_device(dci);
if (rc) {
dev_err(edac->dev, "edac_device_add_device failed\n");
rc = -ENOMEM;
goto err_release_group1;
}
altr_create_edacdev_dbgfs(dci, prv);
list_add(&altdev->next, &edac->a10_ecc_devices);
devres_remove_group(edac->dev, altr_edac_a10_device_add);
return 0;
err_release_group1:
edac_device_free_ctl_info(dci);
err_release_group:
devres_release_group(edac->dev, NULL);
edac_printk(KERN_ERR, EDAC_DEVICE,
"%s:Error setting up EDAC device: %d\n", ecc_name, rc);
return rc;
}