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;
}