in xgene_edac.c [1844:1961]
static int xgene_edac_probe(struct platform_device *pdev)
{
struct xgene_edac *edac;
struct device_node *child;
struct resource *res;
int rc;
edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL);
if (!edac)
return -ENOMEM;
edac->dev = &pdev->dev;
platform_set_drvdata(pdev, edac);
INIT_LIST_HEAD(&edac->mcus);
INIT_LIST_HEAD(&edac->pmds);
INIT_LIST_HEAD(&edac->l3s);
INIT_LIST_HEAD(&edac->socs);
spin_lock_init(&edac->lock);
mutex_init(&edac->mc_lock);
edac->csw_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"regmap-csw");
if (IS_ERR(edac->csw_map)) {
dev_err(edac->dev, "unable to get syscon regmap csw\n");
rc = PTR_ERR(edac->csw_map);
goto out_err;
}
edac->mcba_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"regmap-mcba");
if (IS_ERR(edac->mcba_map)) {
dev_err(edac->dev, "unable to get syscon regmap mcba\n");
rc = PTR_ERR(edac->mcba_map);
goto out_err;
}
edac->mcbb_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"regmap-mcbb");
if (IS_ERR(edac->mcbb_map)) {
dev_err(edac->dev, "unable to get syscon regmap mcbb\n");
rc = PTR_ERR(edac->mcbb_map);
goto out_err;
}
edac->efuse_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"regmap-efuse");
if (IS_ERR(edac->efuse_map)) {
dev_err(edac->dev, "unable to get syscon regmap efuse\n");
rc = PTR_ERR(edac->efuse_map);
goto out_err;
}
/*
* NOTE: The register bus resource is optional for compatibility
* reason.
*/
edac->rb_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"regmap-rb");
if (IS_ERR(edac->rb_map)) {
dev_warn(edac->dev, "missing syscon regmap rb\n");
edac->rb_map = NULL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
edac->pcp_csr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(edac->pcp_csr)) {
dev_err(&pdev->dev, "no PCP resource address\n");
rc = PTR_ERR(edac->pcp_csr);
goto out_err;
}
if (edac_op_state == EDAC_OPSTATE_INT) {
int irq;
int i;
for (i = 0; i < 3; i++) {
irq = platform_get_irq_optional(pdev, i);
if (irq < 0) {
dev_err(&pdev->dev, "No IRQ resource\n");
rc = -EINVAL;
goto out_err;
}
rc = devm_request_irq(&pdev->dev, irq,
xgene_edac_isr, IRQF_SHARED,
dev_name(&pdev->dev), edac);
if (rc) {
dev_err(&pdev->dev,
"Could not request IRQ %d\n", irq);
goto out_err;
}
}
}
edac->dfs = edac_debugfs_create_dir(pdev->dev.kobj.name);
for_each_child_of_node(pdev->dev.of_node, child) {
if (!of_device_is_available(child))
continue;
if (of_device_is_compatible(child, "apm,xgene-edac-mc"))
xgene_edac_mc_add(edac, child);
if (of_device_is_compatible(child, "apm,xgene-edac-pmd"))
xgene_edac_pmd_add(edac, child, 1);
if (of_device_is_compatible(child, "apm,xgene-edac-pmd-v2"))
xgene_edac_pmd_add(edac, child, 2);
if (of_device_is_compatible(child, "apm,xgene-edac-l3"))
xgene_edac_l3_add(edac, child, 1);
if (of_device_is_compatible(child, "apm,xgene-edac-l3-v2"))
xgene_edac_l3_add(edac, child, 2);
if (of_device_is_compatible(child, "apm,xgene-edac-soc"))
xgene_edac_soc_add(edac, child, 0);
if (of_device_is_compatible(child, "apm,xgene-edac-soc-v1"))
xgene_edac_soc_add(edac, child, 1);
}
return 0;
out_err:
return rc;
}