blob: f0b83f9fe62d2a6842ad7a6a80ebe720613109b1 [file] [log] [blame]
Ashwin Chaugule39242ba2012-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>
Ashwin Chaugule39242ba2012-10-29 16:30:05 -040014#include <linux/irq.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070015#include <asm/pmu.h>
16#include <mach/irqs.h>
Ashwin Chaugule39242ba2012-10-29 16:30:05 -040017#include <mach/socinfo.h>
18
Ashwin Chaugulef213bb92012-11-17 11:32:48 -050019/*
20 * If a GIC is present, then all IRQ's < 32 are PPI's and can only be
21 * requested and free'd using the percpu IRQ API.
22 * If a VIC is present, then only the traditional request, free API works.
23 *
24 * All MPCore's have GIC's. The Cortex A5 however may or may not be MPcore, but
25 * it still has a GIC. Except, the 7x27a, which is an A5 and yet has a VIC.
26 * So if the chip is A5 but does not have a GIC, default to the traditional
27 * IRQ {request, free}_irq API.
28 */
29
Ashwin Chauguled82ed3a2012-11-05 10:35:30 -050030#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
Ashwin Chaugulef213bb92012-11-17 11:32:48 -050031 || defined(CONFIG_ARCH_MSM8625) || \
32 (defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
Ashwin Chaugule39242ba2012-10-29 16:30:05 -040033static DEFINE_PER_CPU(u32, pmu_irq_cookie);
34
35static void enable_irq_callback(void *info)
36{
37 int irq = *(unsigned int *)info;
38 enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
39}
40
41static void disable_irq_callback(void *info)
42{
43 int irq = *(unsigned int *)info;
44 disable_percpu_irq(irq);
45}
46
47static int
48multicore_request_irq(int irq, irq_handler_t *handle_irq)
49{
50 int err = 0;
51 int cpu;
52
53 err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
54 &pmu_irq_cookie);
55
56 if (!err) {
57 for_each_cpu(cpu, cpu_online_mask) {
58 smp_call_function_single(cpu,
59 enable_irq_callback, &irq, 1);
60 }
61 }
62
63 return err;
64}
65
66static void
67multicore_free_irq(int irq)
68{
69 int cpu;
70
71 if (irq >= 0) {
72 for_each_cpu(cpu, cpu_online_mask) {
73 smp_call_function_single(cpu,
74 disable_irq_callback, &irq, 1);
75 }
76 free_percpu_irq(irq, &pmu_irq_cookie);
77 }
78}
79
80static struct arm_pmu_platdata multicore_data = {
81 .request_pmu_irq = multicore_request_irq,
82 .free_pmu_irq = multicore_free_irq,
83};
84#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085
Chintan Pandya9a429932012-02-13 19:14:16 +053086static struct resource cpu_pmu_resource[] = {
87 {
88 .start = INT_ARMQC_PERFMON,
89 .end = INT_ARMQC_PERFMON,
90 .flags = IORESOURCE_IRQ,
91 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092};
93
94#ifdef CONFIG_CPU_HAS_L2_PMU
Chintan Pandya9a429932012-02-13 19:14:16 +053095static struct resource l2_pmu_resource[] = {
96 {
97 .start = SC_SICL2PERFMONIRPTREQ,
98 .end = SC_SICL2PERFMONIRPTREQ,
99 .flags = IORESOURCE_IRQ,
100 },
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101};
102
103static struct platform_device l2_pmu_device = {
104 .name = "l2-arm-pmu",
Ashwin Chaugule4a81cb82012-06-07 13:40:54 -0400105 .id = ARM_PMU_DEVICE_L2CC,
Chintan Pandya9a429932012-02-13 19:14:16 +0530106 .resource = l2_pmu_resource,
107 .num_resources = ARRAY_SIZE(l2_pmu_resource),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700108};
109
110#endif
111
112static struct platform_device cpu_pmu_device = {
113 .name = "cpu-arm-pmu",
114 .id = ARM_PMU_DEVICE_CPU,
Chintan Pandya9a429932012-02-13 19:14:16 +0530115 .resource = cpu_pmu_resource,
116 .num_resources = ARRAY_SIZE(cpu_pmu_resource),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117};
118
Ashwin Chauguled82ed3a2012-11-05 10:35:30 -0500119/*
120 * The 8625 is a special case. Due to the requirement of a single
121 * kernel image for the 7x27a and 8625 (which share IRQ headers),
122 * this target breaks the uniformity of IRQ names.
123 * See the file - arch/arm/mach-msm/include/mach/irqs-8625.h
124 */
125#ifdef CONFIG_ARCH_MSM8625
126static struct resource msm8625_cpu_pmu_resource[] = {
127 {
128 .start = MSM8625_INT_ARMQC_PERFMON,
129 .end = MSM8625_INT_ARMQC_PERFMON,
130 .flags = IORESOURCE_IRQ,
131 },
132};
133
134static struct platform_device msm8625_cpu_pmu_device = {
135 .name = "cpu-arm-pmu",
136 .id = ARM_PMU_DEVICE_CPU,
137 .resource = msm8625_cpu_pmu_resource,
138 .num_resources = ARRAY_SIZE(msm8625_cpu_pmu_resource),
139};
140#endif
Ashwin Chaugule39242ba2012-10-29 16:30:05 -0400141
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700142static struct platform_device *pmu_devices[] = {
143 &cpu_pmu_device,
144#ifdef CONFIG_CPU_HAS_L2_PMU
145 &l2_pmu_device,
146#endif
147};
148
149static int __init msm_pmu_init(void)
150{
Ashwin Chaugule39242ba2012-10-29 16:30:05 -0400151 /*
152 * For the targets we know are multicore's set the request/free IRQ
153 * handlers to call the percpu API.
154 * Defaults to unicore API {request,free}_irq().
155 * See arch/arm/kernel/perf_event.c
Ashwin Chaugulef213bb92012-11-17 11:32:48 -0500156 * See Comment above on the A5 and MSM_VIC.
Ashwin Chaugule39242ba2012-10-29 16:30:05 -0400157 */
Ashwin Chaugulef213bb92012-11-17 11:32:48 -0500158#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
159 || (defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
Ashwin Chaugule39242ba2012-10-29 16:30:05 -0400160 cpu_pmu_device.dev.platform_data = &multicore_data;
161#endif
162
Ashwin Chauguled82ed3a2012-11-05 10:35:30 -0500163 /*
164 * The 7x27a and 8625 require a single kernel image.
165 * So we need to check if we're on an 8625 at runtime
166 * and point to the appropriate 'struct resource'.
167 */
168#ifdef CONFIG_ARCH_MSM8625
169 if (cpu_is_msm8625()) {
170 pmu_devices[0] = &msm8625_cpu_pmu_device;
171 msm8625_cpu_pmu_device.dev.platform_data = &multicore_data;
172 }
173#endif
174
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700175 return platform_add_devices(pmu_devices, ARRAY_SIZE(pmu_devices));
176}
177
178arch_initcall(msm_pmu_init);