static int mpc85xx_l2_err_probe()

in mpc85xx_edac.c [489:591]


static int mpc85xx_l2_err_probe(struct platform_device *op)
{
	struct edac_device_ctl_info *edac_dev;
	struct mpc85xx_l2_pdata *pdata;
	struct resource r;
	int res;

	if (!devres_open_group(&op->dev, mpc85xx_l2_err_probe, GFP_KERNEL))
		return -ENOMEM;

	edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
					      "cpu", 1, "L", 1, 2, NULL, 0,
					      edac_dev_idx);
	if (!edac_dev) {
		devres_release_group(&op->dev, mpc85xx_l2_err_probe);
		return -ENOMEM;
	}

	pdata = edac_dev->pvt_info;
	pdata->name = "mpc85xx_l2_err";
	edac_dev->dev = &op->dev;
	dev_set_drvdata(edac_dev->dev, edac_dev);
	edac_dev->ctl_name = pdata->name;
	edac_dev->dev_name = pdata->name;

	res = of_address_to_resource(op->dev.of_node, 0, &r);
	if (res) {
		pr_err("%s: Unable to get resource for L2 err regs\n", __func__);
		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)) {
		pr_err("%s: Error while requesting mem region\n", __func__);
		res = -EBUSY;
		goto err;
	}

	pdata->l2_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
	if (!pdata->l2_vbase) {
		pr_err("%s: Unable to setup L2 err regs\n", __func__);
		res = -ENOMEM;
		goto err;
	}

	out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, ~0);

	orig_l2_err_disable = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS);

	/* clear the err_dis */
	out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, 0);

	edac_dev->mod_name = EDAC_MOD_STR;

	if (edac_op_state == EDAC_OPSTATE_POLL)
		edac_dev->edac_check = mpc85xx_l2_check;

	mpc85xx_set_l2_sysfs_attributes(edac_dev);

	pdata->edac_idx = edac_dev_idx++;

	if (edac_device_add_device(edac_dev) > 0) {
		edac_dbg(3, "failed edac_device_add_device()\n");
		goto err;
	}

	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_l2_isr, IRQF_SHARED,
				       "[EDAC] L2 err", edac_dev);
		if (res < 0) {
			pr_err("%s: Unable to request irq %d for MPC85xx L2 err\n",
				__func__, pdata->irq);
			irq_dispose_mapping(pdata->irq);
			res = -ENODEV;
			goto err2;
		}

		pr_info(EDAC_MOD_STR " acquired irq %d for L2 Err\n", pdata->irq);

		edac_dev->op_state = OP_RUNNING_INTERRUPT;

		out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, L2_EIE_MASK);
	}

	devres_remove_group(&op->dev, mpc85xx_l2_err_probe);

	edac_dbg(3, "success\n");
	pr_info(EDAC_MOD_STR " L2 err registered\n");

	return 0;

err2:
	edac_device_del_device(&op->dev);
err:
	devres_release_group(&op->dev, mpc85xx_l2_err_probe);
	edac_device_free_ctl_info(edac_dev);
	return res;
}