blob: 8d65eea345e5bd45e9c35fabb37d6d1f77682cef [file] [log] [blame]
Ashwin Chaugule6c755b22012-10-29 16:30:05 -04001/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/platform_device.h>
14#include <asm/pmu.h>
15#include <mach/irqs.h>
Ashwin Chaugule6c755b22012-10-29 16:30:05 -040016#include <mach/socinfo.h>
17
18#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP)
19static DEFINE_PER_CPU(u32, pmu_irq_cookie);
20
Ashwin Chaugule6c755b22012-10-29 16:30:05 -040021static int
22multicore_request_irq(int irq, irq_handler_t *handle_irq)
23{
24 int err = 0;
25 int cpu;
26
27 err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
28 &pmu_irq_cookie);
29
30 if (!err) {
31 for_each_cpu(cpu, cpu_online_mask) {
32 smp_call_function_single(cpu,
33 enable_irq_callback, &irq, 1);
34 }
35 }
36
37 return err;
38}
39
40static void
41multicore_free_irq(int irq)
42{
43 int cpu;
44
45 if (irq >= 0) {
46 for_each_cpu(cpu, cpu_online_mask) {
47 smp_call_function_single(cpu,
48 disable_irq_callback, &irq, 1);
49 }
50 free_percpu_irq(irq, &pmu_irq_cookie);
51 }
52}
53
54static struct arm_pmu_platdata multicore_data = {
55 .request_pmu_irq = multicore_request_irq,
56 .free_pmu_irq = multicore_free_irq,
57};
58#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059
Chintan Pandya9a429932012-02-13 19:14:16 +053060static struct resource cpu_pmu_resource[] = {
61 {
62 .start = INT_ARMQC_PERFMON,
63 .end = INT_ARMQC_PERFMON,
64 .flags = IORESOURCE_IRQ,
65 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070066};
67
68#ifdef CONFIG_CPU_HAS_L2_PMU
Chintan Pandya9a429932012-02-13 19:14:16 +053069static struct resource l2_pmu_resource[] = {
70 {
71 .start = SC_SICL2PERFMONIRPTREQ,
72 .end = SC_SICL2PERFMONIRPTREQ,
73 .flags = IORESOURCE_IRQ,
74 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075};
76
77static struct platform_device l2_pmu_device = {
78 .name = "l2-arm-pmu",
Ashwin Chaugule4a81cb82012-06-07 13:40:54 -040079 .id = ARM_PMU_DEVICE_L2CC,
Chintan Pandya9a429932012-02-13 19:14:16 +053080 .resource = l2_pmu_resource,
81 .num_resources = ARRAY_SIZE(l2_pmu_resource),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070082};
83
84#endif
85
86static struct platform_device cpu_pmu_device = {
87 .name = "cpu-arm-pmu",
88 .id = ARM_PMU_DEVICE_CPU,
Chintan Pandya9a429932012-02-13 19:14:16 +053089 .resource = cpu_pmu_resource,
90 .num_resources = ARRAY_SIZE(cpu_pmu_resource),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070091};
92
Ashwin Chaugule6c755b22012-10-29 16:30:05 -040093
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070094static struct platform_device *pmu_devices[] = {
95 &cpu_pmu_device,
96#ifdef CONFIG_CPU_HAS_L2_PMU
97 &l2_pmu_device,
98#endif
99};
100
101static int __init msm_pmu_init(void)
102{
Ashwin Chaugule6c755b22012-10-29 16:30:05 -0400103 /*
104 * For the targets we know are multicore's set the request/free IRQ
105 * handlers to call the percpu API.
106 * Defaults to unicore API {request,free}_irq().
107 * See arch/arm/kernel/perf_event.c
108 */
109#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP)
110 cpu_pmu_device.dev.platform_data = &multicore_data;
111#endif
112
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700113 return platform_add_devices(pmu_devices, ARRAY_SIZE(pmu_devices));
114}
115
116arch_initcall(msm_pmu_init);