static int dmc620_pmu_device_probe()

in arm_dmc620_pmu.c [630:697]


static int dmc620_pmu_device_probe(struct platform_device *pdev)
{
	struct dmc620_pmu *dmc620_pmu;
	struct resource *res;
	char *name;
	int irq_num;
	int i, ret;

	dmc620_pmu = devm_kzalloc(&pdev->dev,
			sizeof(struct dmc620_pmu), GFP_KERNEL);
	if (!dmc620_pmu)
		return -ENOMEM;

	platform_set_drvdata(pdev, dmc620_pmu);

	dmc620_pmu->pmu = (struct pmu) {
		.module = THIS_MODULE,
		.capabilities	= PERF_PMU_CAP_NO_EXCLUDE,
		.task_ctx_nr	= perf_invalid_context,
		.event_init	= dmc620_pmu_event_init,
		.add		= dmc620_pmu_add,
		.del		= dmc620_pmu_del,
		.start		= dmc620_pmu_start,
		.stop		= dmc620_pmu_stop,
		.read		= dmc620_pmu_read,
		.attr_groups	= dmc620_pmu_attr_groups,
	};

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	dmc620_pmu->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(dmc620_pmu->base))
		return PTR_ERR(dmc620_pmu->base);

	/* Make sure device is reset before enabling interrupt */
	for (i = 0; i < DMC620_PMU_MAX_COUNTERS; i++)
		dmc620_pmu_creg_write(dmc620_pmu, i, DMC620_PMU_COUNTERn_CONTROL, 0);
	writel(0, dmc620_pmu->base + DMC620_PMU_OVERFLOW_STATUS_CLKDIV2);
	writel(0, dmc620_pmu->base + DMC620_PMU_OVERFLOW_STATUS_CLK);

	irq_num = platform_get_irq(pdev, 0);
	if (irq_num < 0)
		return irq_num;

	ret = dmc620_pmu_get_irq(dmc620_pmu, irq_num);
	if (ret)
		return ret;

	name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
				  "%s_%llx", DMC620_PMUNAME,
				  (u64)(res->start >> DMC620_PA_SHIFT));
	if (!name) {
		dev_err(&pdev->dev,
			  "Create name failed, PMU @%pa\n", &res->start);
		ret = -ENOMEM;
		goto out_teardown_dev;
	}

	ret = perf_pmu_register(&dmc620_pmu->pmu, name, -1);
	if (ret)
		goto out_teardown_dev;

	return 0;

out_teardown_dev:
	dmc620_pmu_put_irq(dmc620_pmu);
	synchronize_rcu();
	return ret;
}