ARM: perf: add devicetree bindings for 11MPcore, A5, A7 and A15 PMUs
[firefly-linux-kernel-4.4.55.git] / arch / arm / kernel / perf_event.c
index a02eada3aa5d06036027ac1241e652d5032781bd..3aa3388491334a7834c198c91276a3d4a62a4493 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
@@ -47,17 +48,14 @@ static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
 /* Set at runtime when we know what CPU type we are. */
 static struct arm_pmu *cpu_pmu;
 
-enum arm_perf_pmu_ids
-armpmu_get_pmu_id(void)
+const char *perf_pmu_name(void)
 {
-       int id = -ENODEV;
-
-       if (cpu_pmu != NULL)
-               id = cpu_pmu->id;
+       if (!cpu_pmu)
+               return NULL;
 
-       return id;
+       return cpu_pmu->pmu.name;
 }
-EXPORT_SYMBOL_GPL(armpmu_get_pmu_id);
+EXPORT_SYMBOL_GPL(perf_pmu_name);
 
 int perf_num_counters(void)
 {
@@ -367,8 +365,6 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
 {
        int i, irq, irqs;
        struct platform_device *pmu_device = armpmu->plat_device;
-       struct arm_pmu_platdata *plat =
-               dev_get_platdata(&pmu_device->dev);
 
        irqs = min(pmu_device->num_resources, num_possible_cpus());
 
@@ -376,13 +372,11 @@ armpmu_release_hardware(struct arm_pmu *armpmu)
                if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
                        continue;
                irq = platform_get_irq(pmu_device, i);
-               if (irq >= 0) {
-                       if (plat && plat->disable_irq)
-                               plat->disable_irq(irq);
+               if (irq >= 0)
                        free_irq(irq, armpmu);
-               }
        }
 
+       pm_runtime_put_sync(&pmu_device->dev);
        release_pmu(armpmu->type);
 }
 
@@ -415,6 +409,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
                return -ENODEV;
        }
 
+       pm_runtime_get_sync(&pmu_device->dev);
+
        for (i = 0; i < irqs; ++i) {
                err = 0;
                irq = platform_get_irq(pmu_device, i);
@@ -440,8 +436,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
                                irq);
                        armpmu_release_hardware(armpmu);
                        return err;
-               } else if (plat && plat->enable_irq)
-                       plat->enable_irq(irq);
+               }
 
                cpumask_set_cpu(i, &armpmu->active_irqs);
        }
@@ -584,6 +579,28 @@ static void armpmu_disable(struct pmu *pmu)
        armpmu->stop();
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int armpmu_runtime_resume(struct device *dev)
+{
+       struct arm_pmu_platdata *plat = dev_get_platdata(dev);
+
+       if (plat && plat->runtime_resume)
+               return plat->runtime_resume(dev);
+
+       return 0;
+}
+
+static int armpmu_runtime_suspend(struct device *dev)
+{
+       struct arm_pmu_platdata *plat = dev_get_platdata(dev);
+
+       if (plat && plat->runtime_suspend)
+               return plat->runtime_suspend(dev);
+
+       return 0;
+}
+#endif
+
 static void __init armpmu_init(struct arm_pmu *armpmu)
 {
        atomic_set(&armpmu->active_events, 0);
@@ -629,10 +646,14 @@ arch_initcall(cpu_pmu_reset);
  * PMU platform driver and devicetree bindings.
  */
 static struct of_device_id armpmu_of_device_ids[] = {
+       {.compatible = "arm,cortex-a15-pmu"},
        {.compatible = "arm,cortex-a9-pmu"},
        {.compatible = "arm,cortex-a8-pmu"},
-       {.compatible = "arm,arm1136-pmu"},
+       {.compatible = "arm,cortex-a7-pmu"},
+       {.compatible = "arm,cortex-a5-pmu"},
+       {.compatible = "arm,arm11mpcore-pmu"},
        {.compatible = "arm,arm1176-pmu"},
+       {.compatible = "arm,arm1136-pmu"},
        {},
 };
 
@@ -650,9 +671,14 @@ static int __devinit armpmu_device_probe(struct platform_device *pdev)
        return 0;
 }
 
+static const struct dev_pm_ops armpmu_dev_pm_ops = {
+       SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
+};
+
 static struct platform_driver armpmu_driver = {
        .driver         = {
                .name   = "arm-pmu",
+               .pm     = &armpmu_dev_pm_ops,
                .of_match_table = armpmu_of_device_ids,
        },
        .probe          = armpmu_device_probe,
@@ -760,7 +786,7 @@ init_hw_perf_events(void)
                        cpu_pmu->name, cpu_pmu->num_events);
                cpu_pmu_init(cpu_pmu);
                register_cpu_notifier(&pmu_cpu_notifier);
-               armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
+               armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
        } else {
                pr_info("no hardware support available\n");
        }