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 ab243b87118da54628c25b0069ecc52cc0d2f717..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>
@@ -364,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());
 
@@ -373,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);
 }
 
@@ -412,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);
@@ -437,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);
        }
@@ -581,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);
@@ -626,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"},
        {},
 };
 
@@ -647,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,