Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
[pandora-kernel.git] / arch / arm / kernel / perf_event_v7.c
1 /*
2  * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code.
3  *
4  * ARMv7 support: Jean Pihet <jpihet@mvista.com>
5  * 2010 (c) MontaVista Software, LLC.
6  *
7  * Copied from ARMv6 code, with the low level code inspired
8  *  by the ARMv7 Oprofile code.
9  *
10  * Cortex-A8 has up to 4 configurable performance counters and
11  *  a single cycle counter.
12  * Cortex-A9 has up to 31 configurable performance counters and
13  *  a single cycle counter.
14  *
15  * All counters can be enabled/disabled and IRQ masked separately. The cycle
16  *  counter and all 4 performance counters together can be reset separately.
17  */
18
19 #ifdef CONFIG_CPU_V7
20 /*
21  * Common ARMv7 event types
22  *
23  * Note: An implementation may not be able to count all of these events
24  * but the encodings are considered to be `reserved' in the case that
25  * they are not available.
26  */
27 enum armv7_perf_types {
28         ARMV7_PERFCTR_PMNC_SW_INCR              = 0x00,
29         ARMV7_PERFCTR_IFETCH_MISS               = 0x01,
30         ARMV7_PERFCTR_ITLB_MISS                 = 0x02,
31         ARMV7_PERFCTR_DCACHE_REFILL             = 0x03, /* L1 */
32         ARMV7_PERFCTR_DCACHE_ACCESS             = 0x04, /* L1 */
33         ARMV7_PERFCTR_DTLB_REFILL               = 0x05,
34         ARMV7_PERFCTR_DREAD                     = 0x06,
35         ARMV7_PERFCTR_DWRITE                    = 0x07,
36         ARMV7_PERFCTR_INSTR_EXECUTED            = 0x08,
37         ARMV7_PERFCTR_EXC_TAKEN                 = 0x09,
38         ARMV7_PERFCTR_EXC_EXECUTED              = 0x0A,
39         ARMV7_PERFCTR_CID_WRITE                 = 0x0B,
40         /* ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS.
41          * It counts:
42          *  - all branch instructions,
43          *  - instructions that explicitly write the PC,
44          *  - exception generating instructions.
45          */
46         ARMV7_PERFCTR_PC_WRITE                  = 0x0C,
47         ARMV7_PERFCTR_PC_IMM_BRANCH             = 0x0D,
48         ARMV7_PERFCTR_PC_PROC_RETURN            = 0x0E,
49         ARMV7_PERFCTR_UNALIGNED_ACCESS          = 0x0F,
50
51         /* These events are defined by the PMUv2 supplement (ARM DDI 0457A). */
52         ARMV7_PERFCTR_PC_BRANCH_MIS_PRED        = 0x10,
53         ARMV7_PERFCTR_CLOCK_CYCLES              = 0x11,
54         ARMV7_PERFCTR_PC_BRANCH_PRED            = 0x12,
55         ARMV7_PERFCTR_MEM_ACCESS                = 0x13,
56         ARMV7_PERFCTR_L1_ICACHE_ACCESS          = 0x14,
57         ARMV7_PERFCTR_L1_DCACHE_WB              = 0x15,
58         ARMV7_PERFCTR_L2_DCACHE_ACCESS          = 0x16,
59         ARMV7_PERFCTR_L2_DCACHE_REFILL          = 0x17,
60         ARMV7_PERFCTR_L2_DCACHE_WB              = 0x18,
61         ARMV7_PERFCTR_BUS_ACCESS                = 0x19,
62         ARMV7_PERFCTR_MEMORY_ERROR              = 0x1A,
63         ARMV7_PERFCTR_INSTR_SPEC                = 0x1B,
64         ARMV7_PERFCTR_TTBR_WRITE                = 0x1C,
65         ARMV7_PERFCTR_BUS_CYCLES                = 0x1D,
66
67         ARMV7_PERFCTR_CPU_CYCLES                = 0xFF
68 };
69
70 /* ARMv7 Cortex-A8 specific event types */
71 enum armv7_a8_perf_types {
72         ARMV7_PERFCTR_WRITE_BUFFER_FULL         = 0x40,
73         ARMV7_PERFCTR_L2_STORE_MERGED           = 0x41,
74         ARMV7_PERFCTR_L2_STORE_BUFF             = 0x42,
75         ARMV7_PERFCTR_L2_ACCESS                 = 0x43,
76         ARMV7_PERFCTR_L2_CACH_MISS              = 0x44,
77         ARMV7_PERFCTR_AXI_READ_CYCLES           = 0x45,
78         ARMV7_PERFCTR_AXI_WRITE_CYCLES          = 0x46,
79         ARMV7_PERFCTR_MEMORY_REPLAY             = 0x47,
80         ARMV7_PERFCTR_UNALIGNED_ACCESS_REPLAY   = 0x48,
81         ARMV7_PERFCTR_L1_DATA_MISS              = 0x49,
82         ARMV7_PERFCTR_L1_INST_MISS              = 0x4A,
83         ARMV7_PERFCTR_L1_DATA_COLORING          = 0x4B,
84         ARMV7_PERFCTR_L1_NEON_DATA              = 0x4C,
85         ARMV7_PERFCTR_L1_NEON_CACH_DATA         = 0x4D,
86         ARMV7_PERFCTR_L2_NEON                   = 0x4E,
87         ARMV7_PERFCTR_L2_NEON_HIT               = 0x4F,
88         ARMV7_PERFCTR_L1_INST                   = 0x50,
89         ARMV7_PERFCTR_PC_RETURN_MIS_PRED        = 0x51,
90         ARMV7_PERFCTR_PC_BRANCH_FAILED          = 0x52,
91         ARMV7_PERFCTR_PC_BRANCH_TAKEN           = 0x53,
92         ARMV7_PERFCTR_PC_BRANCH_EXECUTED        = 0x54,
93         ARMV7_PERFCTR_OP_EXECUTED               = 0x55,
94         ARMV7_PERFCTR_CYCLES_INST_STALL         = 0x56,
95         ARMV7_PERFCTR_CYCLES_INST               = 0x57,
96         ARMV7_PERFCTR_CYCLES_NEON_DATA_STALL    = 0x58,
97         ARMV7_PERFCTR_CYCLES_NEON_INST_STALL    = 0x59,
98         ARMV7_PERFCTR_NEON_CYCLES               = 0x5A,
99
100         ARMV7_PERFCTR_PMU0_EVENTS               = 0x70,
101         ARMV7_PERFCTR_PMU1_EVENTS               = 0x71,
102         ARMV7_PERFCTR_PMU_EVENTS                = 0x72,
103 };
104
105 /* ARMv7 Cortex-A9 specific event types */
106 enum armv7_a9_perf_types {
107         ARMV7_PERFCTR_JAVA_HW_BYTECODE_EXEC     = 0x40,
108         ARMV7_PERFCTR_JAVA_SW_BYTECODE_EXEC     = 0x41,
109         ARMV7_PERFCTR_JAZELLE_BRANCH_EXEC       = 0x42,
110
111         ARMV7_PERFCTR_COHERENT_LINE_MISS        = 0x50,
112         ARMV7_PERFCTR_COHERENT_LINE_HIT         = 0x51,
113
114         ARMV7_PERFCTR_ICACHE_DEP_STALL_CYCLES   = 0x60,
115         ARMV7_PERFCTR_DCACHE_DEP_STALL_CYCLES   = 0x61,
116         ARMV7_PERFCTR_TLB_MISS_DEP_STALL_CYCLES = 0x62,
117         ARMV7_PERFCTR_STREX_EXECUTED_PASSED     = 0x63,
118         ARMV7_PERFCTR_STREX_EXECUTED_FAILED     = 0x64,
119         ARMV7_PERFCTR_DATA_EVICTION             = 0x65,
120         ARMV7_PERFCTR_ISSUE_STAGE_NO_INST       = 0x66,
121         ARMV7_PERFCTR_ISSUE_STAGE_EMPTY         = 0x67,
122         ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE  = 0x68,
123
124         ARMV7_PERFCTR_PREDICTABLE_FUNCT_RETURNS = 0x6E,
125
126         ARMV7_PERFCTR_MAIN_UNIT_EXECUTED_INST   = 0x70,
127         ARMV7_PERFCTR_SECOND_UNIT_EXECUTED_INST = 0x71,
128         ARMV7_PERFCTR_LD_ST_UNIT_EXECUTED_INST  = 0x72,
129         ARMV7_PERFCTR_FP_EXECUTED_INST          = 0x73,
130         ARMV7_PERFCTR_NEON_EXECUTED_INST        = 0x74,
131
132         ARMV7_PERFCTR_PLD_FULL_DEP_STALL_CYCLES = 0x80,
133         ARMV7_PERFCTR_DATA_WR_DEP_STALL_CYCLES  = 0x81,
134         ARMV7_PERFCTR_ITLB_MISS_DEP_STALL_CYCLES        = 0x82,
135         ARMV7_PERFCTR_DTLB_MISS_DEP_STALL_CYCLES        = 0x83,
136         ARMV7_PERFCTR_MICRO_ITLB_MISS_DEP_STALL_CYCLES  = 0x84,
137         ARMV7_PERFCTR_MICRO_DTLB_MISS_DEP_STALL_CYCLES  = 0x85,
138         ARMV7_PERFCTR_DMB_DEP_STALL_CYCLES      = 0x86,
139
140         ARMV7_PERFCTR_INTGR_CLK_ENABLED_CYCLES  = 0x8A,
141         ARMV7_PERFCTR_DATA_ENGINE_CLK_EN_CYCLES = 0x8B,
142
143         ARMV7_PERFCTR_ISB_INST                  = 0x90,
144         ARMV7_PERFCTR_DSB_INST                  = 0x91,
145         ARMV7_PERFCTR_DMB_INST                  = 0x92,
146         ARMV7_PERFCTR_EXT_INTERRUPTS            = 0x93,
147
148         ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_COMPLETED     = 0xA0,
149         ARMV7_PERFCTR_PLE_CACHE_LINE_RQST_SKIPPED       = 0xA1,
150         ARMV7_PERFCTR_PLE_FIFO_FLUSH            = 0xA2,
151         ARMV7_PERFCTR_PLE_RQST_COMPLETED        = 0xA3,
152         ARMV7_PERFCTR_PLE_FIFO_OVERFLOW         = 0xA4,
153         ARMV7_PERFCTR_PLE_RQST_PROG             = 0xA5
154 };
155
156 /* ARMv7 Cortex-A5 specific event types */
157 enum armv7_a5_perf_types {
158         ARMV7_PERFCTR_IRQ_TAKEN                 = 0x86,
159         ARMV7_PERFCTR_FIQ_TAKEN                 = 0x87,
160
161         ARMV7_PERFCTR_EXT_MEM_RQST              = 0xc0,
162         ARMV7_PERFCTR_NC_EXT_MEM_RQST           = 0xc1,
163         ARMV7_PERFCTR_PREFETCH_LINEFILL         = 0xc2,
164         ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP    = 0xc3,
165         ARMV7_PERFCTR_ENTER_READ_ALLOC          = 0xc4,
166         ARMV7_PERFCTR_READ_ALLOC                = 0xc5,
167
168         ARMV7_PERFCTR_STALL_SB_FULL             = 0xc9,
169 };
170
171 /* ARMv7 Cortex-A15 specific event types */
172 enum armv7_a15_perf_types {
173         ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS     = 0x40,
174         ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS    = 0x41,
175         ARMV7_PERFCTR_L1_DCACHE_READ_REFILL     = 0x42,
176         ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL    = 0x43,
177
178         ARMV7_PERFCTR_L1_DTLB_READ_REFILL       = 0x4C,
179         ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL      = 0x4D,
180
181         ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS     = 0x50,
182         ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS    = 0x51,
183         ARMV7_PERFCTR_L2_DCACHE_READ_REFILL     = 0x52,
184         ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL    = 0x53,
185
186         ARMV7_PERFCTR_SPEC_PC_WRITE             = 0x76,
187 };
188
189 /*
190  * Cortex-A8 HW events mapping
191  *
192  * The hardware events that we support. We do support cache operations but
193  * we have harvard caches and no way to combine instruction and data
194  * accesses/misses in hardware.
195  */
196 static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = {
197         [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
198         [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV7_PERFCTR_INSTR_EXECUTED,
199         [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
200         [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
201         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
202         [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
203         [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
204 };
205
206 static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
207                                           [PERF_COUNT_HW_CACHE_OP_MAX]
208                                           [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
209         [C(L1D)] = {
210                 /*
211                  * The performance counters don't differentiate between read
212                  * and write accesses/misses so this isn't strictly correct,
213                  * but it's the best we can do. Writes and reads get
214                  * combined.
215                  */
216                 [C(OP_READ)] = {
217                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
218                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
219                 },
220                 [C(OP_WRITE)] = {
221                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
222                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
223                 },
224                 [C(OP_PREFETCH)] = {
225                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
226                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
227                 },
228         },
229         [C(L1I)] = {
230                 [C(OP_READ)] = {
231                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
232                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
233                 },
234                 [C(OP_WRITE)] = {
235                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_INST,
236                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_INST_MISS,
237                 },
238                 [C(OP_PREFETCH)] = {
239                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
240                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
241                 },
242         },
243         [C(LL)] = {
244                 [C(OP_READ)] = {
245                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
246                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
247                 },
248                 [C(OP_WRITE)] = {
249                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_ACCESS,
250                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACH_MISS,
251                 },
252                 [C(OP_PREFETCH)] = {
253                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
254                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
255                 },
256         },
257         [C(DTLB)] = {
258                 [C(OP_READ)] = {
259                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
260                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
261                 },
262                 [C(OP_WRITE)] = {
263                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
264                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
265                 },
266                 [C(OP_PREFETCH)] = {
267                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
268                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
269                 },
270         },
271         [C(ITLB)] = {
272                 [C(OP_READ)] = {
273                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
274                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
275                 },
276                 [C(OP_WRITE)] = {
277                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
278                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
279                 },
280                 [C(OP_PREFETCH)] = {
281                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
282                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
283                 },
284         },
285         [C(BPU)] = {
286                 [C(OP_READ)] = {
287                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
288                         [C(RESULT_MISS)]
289                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
290                 },
291                 [C(OP_WRITE)] = {
292                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
293                         [C(RESULT_MISS)]
294                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
295                 },
296                 [C(OP_PREFETCH)] = {
297                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
298                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
299                 },
300         },
301         [C(NODE)] = {
302                 [C(OP_READ)] = {
303                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
304                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
305                 },
306                 [C(OP_WRITE)] = {
307                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
308                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
309                 },
310                 [C(OP_PREFETCH)] = {
311                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
312                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
313                 },
314         },
315 };
316
317 /*
318  * Cortex-A9 HW events mapping
319  */
320 static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = {
321         [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
322         [PERF_COUNT_HW_INSTRUCTIONS]        =
323                                         ARMV7_PERFCTR_INST_OUT_OF_RENAME_STAGE,
324         [PERF_COUNT_HW_CACHE_REFERENCES]    = ARMV7_PERFCTR_COHERENT_LINE_HIT,
325         [PERF_COUNT_HW_CACHE_MISSES]        = ARMV7_PERFCTR_COHERENT_LINE_MISS,
326         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
327         [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
328         [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_CLOCK_CYCLES,
329 };
330
331 static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
332                                           [PERF_COUNT_HW_CACHE_OP_MAX]
333                                           [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
334         [C(L1D)] = {
335                 /*
336                  * The performance counters don't differentiate between read
337                  * and write accesses/misses so this isn't strictly correct,
338                  * but it's the best we can do. Writes and reads get
339                  * combined.
340                  */
341                 [C(OP_READ)] = {
342                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
343                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
344                 },
345                 [C(OP_WRITE)] = {
346                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_DCACHE_ACCESS,
347                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DCACHE_REFILL,
348                 },
349                 [C(OP_PREFETCH)] = {
350                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
351                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
352                 },
353         },
354         [C(L1I)] = {
355                 [C(OP_READ)] = {
356                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
357                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
358                 },
359                 [C(OP_WRITE)] = {
360                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
361                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
362                 },
363                 [C(OP_PREFETCH)] = {
364                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
365                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
366                 },
367         },
368         [C(LL)] = {
369                 [C(OP_READ)] = {
370                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
371                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
372                 },
373                 [C(OP_WRITE)] = {
374                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
375                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
376                 },
377                 [C(OP_PREFETCH)] = {
378                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
379                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
380                 },
381         },
382         [C(DTLB)] = {
383                 [C(OP_READ)] = {
384                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
385                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
386                 },
387                 [C(OP_WRITE)] = {
388                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
389                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
390                 },
391                 [C(OP_PREFETCH)] = {
392                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
393                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
394                 },
395         },
396         [C(ITLB)] = {
397                 [C(OP_READ)] = {
398                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
399                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
400                 },
401                 [C(OP_WRITE)] = {
402                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
403                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
404                 },
405                 [C(OP_PREFETCH)] = {
406                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
407                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
408                 },
409         },
410         [C(BPU)] = {
411                 [C(OP_READ)] = {
412                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
413                         [C(RESULT_MISS)]
414                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
415                 },
416                 [C(OP_WRITE)] = {
417                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_WRITE,
418                         [C(RESULT_MISS)]
419                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
420                 },
421                 [C(OP_PREFETCH)] = {
422                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
423                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
424                 },
425         },
426         [C(NODE)] = {
427                 [C(OP_READ)] = {
428                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
429                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
430                 },
431                 [C(OP_WRITE)] = {
432                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
433                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
434                 },
435                 [C(OP_PREFETCH)] = {
436                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
437                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
438                 },
439         },
440 };
441
442 /*
443  * Cortex-A5 HW events mapping
444  */
445 static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = {
446         [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
447         [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV7_PERFCTR_INSTR_EXECUTED,
448         [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
449         [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
450         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
451         [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
452         [PERF_COUNT_HW_BUS_CYCLES]          = HW_OP_UNSUPPORTED,
453 };
454
455 static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
456                                         [PERF_COUNT_HW_CACHE_OP_MAX]
457                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
458         [C(L1D)] = {
459                 [C(OP_READ)] = {
460                         [C(RESULT_ACCESS)]
461                                         = ARMV7_PERFCTR_DCACHE_ACCESS,
462                         [C(RESULT_MISS)]
463                                         = ARMV7_PERFCTR_DCACHE_REFILL,
464                 },
465                 [C(OP_WRITE)] = {
466                         [C(RESULT_ACCESS)]
467                                         = ARMV7_PERFCTR_DCACHE_ACCESS,
468                         [C(RESULT_MISS)]
469                                         = ARMV7_PERFCTR_DCACHE_REFILL,
470                 },
471                 [C(OP_PREFETCH)] = {
472                         [C(RESULT_ACCESS)]
473                                         = ARMV7_PERFCTR_PREFETCH_LINEFILL,
474                         [C(RESULT_MISS)]
475                                         = ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
476                 },
477         },
478         [C(L1I)] = {
479                 [C(OP_READ)] = {
480                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
481                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
482                 },
483                 [C(OP_WRITE)] = {
484                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
485                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
486                 },
487                 /*
488                  * The prefetch counters don't differentiate between the I
489                  * side and the D side.
490                  */
491                 [C(OP_PREFETCH)] = {
492                         [C(RESULT_ACCESS)]
493                                         = ARMV7_PERFCTR_PREFETCH_LINEFILL,
494                         [C(RESULT_MISS)]
495                                         = ARMV7_PERFCTR_PREFETCH_LINEFILL_DROP,
496                 },
497         },
498         [C(LL)] = {
499                 [C(OP_READ)] = {
500                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
501                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
502                 },
503                 [C(OP_WRITE)] = {
504                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
505                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
506                 },
507                 [C(OP_PREFETCH)] = {
508                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
509                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
510                 },
511         },
512         [C(DTLB)] = {
513                 [C(OP_READ)] = {
514                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
515                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
516                 },
517                 [C(OP_WRITE)] = {
518                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
519                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
520                 },
521                 [C(OP_PREFETCH)] = {
522                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
523                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
524                 },
525         },
526         [C(ITLB)] = {
527                 [C(OP_READ)] = {
528                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
529                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
530                 },
531                 [C(OP_WRITE)] = {
532                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
533                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
534                 },
535                 [C(OP_PREFETCH)] = {
536                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
537                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
538                 },
539         },
540         [C(BPU)] = {
541                 [C(OP_READ)] = {
542                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
543                         [C(RESULT_MISS)]
544                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
545                 },
546                 [C(OP_WRITE)] = {
547                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
548                         [C(RESULT_MISS)]
549                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
550                 },
551                 [C(OP_PREFETCH)] = {
552                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
553                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
554                 },
555         },
556 };
557
558 /*
559  * Cortex-A15 HW events mapping
560  */
561 static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = {
562         [PERF_COUNT_HW_CPU_CYCLES]          = ARMV7_PERFCTR_CPU_CYCLES,
563         [PERF_COUNT_HW_INSTRUCTIONS]        = ARMV7_PERFCTR_INSTR_EXECUTED,
564         [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
565         [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
566         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_SPEC_PC_WRITE,
567         [PERF_COUNT_HW_BRANCH_MISSES]       = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
568         [PERF_COUNT_HW_BUS_CYCLES]          = ARMV7_PERFCTR_BUS_CYCLES,
569 };
570
571 static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
572                                         [PERF_COUNT_HW_CACHE_OP_MAX]
573                                         [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
574         [C(L1D)] = {
575                 [C(OP_READ)] = {
576                         [C(RESULT_ACCESS)]
577                                         = ARMV7_PERFCTR_L1_DCACHE_READ_ACCESS,
578                         [C(RESULT_MISS)]
579                                         = ARMV7_PERFCTR_L1_DCACHE_READ_REFILL,
580                 },
581                 [C(OP_WRITE)] = {
582                         [C(RESULT_ACCESS)]
583                                         = ARMV7_PERFCTR_L1_DCACHE_WRITE_ACCESS,
584                         [C(RESULT_MISS)]
585                                         = ARMV7_PERFCTR_L1_DCACHE_WRITE_REFILL,
586                 },
587                 [C(OP_PREFETCH)] = {
588                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
589                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
590                 },
591         },
592         [C(L1I)] = {
593                 /*
594                  * Not all performance counters differentiate between read
595                  * and write accesses/misses so we're not always strictly
596                  * correct, but it's the best we can do. Writes and reads get
597                  * combined in these cases.
598                  */
599                 [C(OP_READ)] = {
600                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
601                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
602                 },
603                 [C(OP_WRITE)] = {
604                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
605                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_IFETCH_MISS,
606                 },
607                 [C(OP_PREFETCH)] = {
608                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
609                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
610                 },
611         },
612         [C(LL)] = {
613                 [C(OP_READ)] = {
614                         [C(RESULT_ACCESS)]
615                                         = ARMV7_PERFCTR_L2_DCACHE_READ_ACCESS,
616                         [C(RESULT_MISS)]
617                                         = ARMV7_PERFCTR_L2_DCACHE_READ_REFILL,
618                 },
619                 [C(OP_WRITE)] = {
620                         [C(RESULT_ACCESS)]
621                                         = ARMV7_PERFCTR_L2_DCACHE_WRITE_ACCESS,
622                         [C(RESULT_MISS)]
623                                         = ARMV7_PERFCTR_L2_DCACHE_WRITE_REFILL,
624                 },
625                 [C(OP_PREFETCH)] = {
626                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
627                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
628                 },
629         },
630         [C(DTLB)] = {
631                 [C(OP_READ)] = {
632                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
633                         [C(RESULT_MISS)]
634                                         = ARMV7_PERFCTR_L1_DTLB_READ_REFILL,
635                 },
636                 [C(OP_WRITE)] = {
637                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
638                         [C(RESULT_MISS)]
639                                         = ARMV7_PERFCTR_L1_DTLB_WRITE_REFILL,
640                 },
641                 [C(OP_PREFETCH)] = {
642                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
643                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
644                 },
645         },
646         [C(ITLB)] = {
647                 [C(OP_READ)] = {
648                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
649                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
650                 },
651                 [C(OP_WRITE)] = {
652                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
653                         [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_MISS,
654                 },
655                 [C(OP_PREFETCH)] = {
656                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
657                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
658                 },
659         },
660         [C(BPU)] = {
661                 [C(OP_READ)] = {
662                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
663                         [C(RESULT_MISS)]
664                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
665                 },
666                 [C(OP_WRITE)] = {
667                         [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
668                         [C(RESULT_MISS)]
669                                         = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
670                 },
671                 [C(OP_PREFETCH)] = {
672                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
673                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
674                 },
675         },
676 };
677
678 /*
679  * Perf Events counters
680  */
681 enum armv7_counters {
682         ARMV7_CYCLE_COUNTER             = 1,    /* Cycle counter */
683         ARMV7_COUNTER0                  = 2,    /* First event counter */
684 };
685
686 /*
687  * The cycle counter is ARMV7_CYCLE_COUNTER.
688  * The first event counter is ARMV7_COUNTER0.
689  * The last event counter is (ARMV7_COUNTER0 + armpmu->num_events - 1).
690  */
691 #define ARMV7_COUNTER_LAST      (ARMV7_COUNTER0 + armpmu->num_events - 1)
692
693 /*
694  * ARMv7 low level PMNC access
695  */
696
697 /*
698  * Per-CPU PMNC: config reg
699  */
700 #define ARMV7_PMNC_E            (1 << 0) /* Enable all counters */
701 #define ARMV7_PMNC_P            (1 << 1) /* Reset all counters */
702 #define ARMV7_PMNC_C            (1 << 2) /* Cycle counter reset */
703 #define ARMV7_PMNC_D            (1 << 3) /* CCNT counts every 64th cpu cycle */
704 #define ARMV7_PMNC_X            (1 << 4) /* Export to ETM */
705 #define ARMV7_PMNC_DP           (1 << 5) /* Disable CCNT if non-invasive debug*/
706 #define ARMV7_PMNC_N_SHIFT      11       /* Number of counters supported */
707 #define ARMV7_PMNC_N_MASK       0x1f
708 #define ARMV7_PMNC_MASK         0x3f     /* Mask for writable bits */
709
710 /*
711  * Available counters
712  */
713 #define ARMV7_CNT0              0       /* First event counter */
714 #define ARMV7_CCNT              31      /* Cycle counter */
715
716 /* Perf Event to low level counters mapping */
717 #define ARMV7_EVENT_CNT_TO_CNTx (ARMV7_COUNTER0 - ARMV7_CNT0)
718
719 /*
720  * CNTENS: counters enable reg
721  */
722 #define ARMV7_CNTENS_P(idx)     (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
723 #define ARMV7_CNTENS_C          (1 << ARMV7_CCNT)
724
725 /*
726  * CNTENC: counters disable reg
727  */
728 #define ARMV7_CNTENC_P(idx)     (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
729 #define ARMV7_CNTENC_C          (1 << ARMV7_CCNT)
730
731 /*
732  * INTENS: counters overflow interrupt enable reg
733  */
734 #define ARMV7_INTENS_P(idx)     (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
735 #define ARMV7_INTENS_C          (1 << ARMV7_CCNT)
736
737 /*
738  * INTENC: counters overflow interrupt disable reg
739  */
740 #define ARMV7_INTENC_P(idx)     (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
741 #define ARMV7_INTENC_C          (1 << ARMV7_CCNT)
742
743 /*
744  * EVTSEL: Event selection reg
745  */
746 #define ARMV7_EVTSEL_MASK       0xff            /* Mask for writable bits */
747
748 /*
749  * SELECT: Counter selection reg
750  */
751 #define ARMV7_SELECT_MASK       0x1f            /* Mask for writable bits */
752
753 /*
754  * FLAG: counters overflow flag status reg
755  */
756 #define ARMV7_FLAG_P(idx)       (1 << (idx - ARMV7_EVENT_CNT_TO_CNTx))
757 #define ARMV7_FLAG_C            (1 << ARMV7_CCNT)
758 #define ARMV7_FLAG_MASK         0xffffffff      /* Mask for writable bits */
759 #define ARMV7_OVERFLOWED_MASK   ARMV7_FLAG_MASK
760
761 static inline unsigned long armv7_pmnc_read(void)
762 {
763         u32 val;
764         asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val));
765         return val;
766 }
767
768 static inline void armv7_pmnc_write(unsigned long val)
769 {
770         val &= ARMV7_PMNC_MASK;
771         isb();
772         asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
773 }
774
775 static inline int armv7_pmnc_has_overflowed(unsigned long pmnc)
776 {
777         return pmnc & ARMV7_OVERFLOWED_MASK;
778 }
779
780 static inline int armv7_pmnc_counter_has_overflowed(unsigned long pmnc,
781                                         enum armv7_counters counter)
782 {
783         int ret = 0;
784
785         if (counter == ARMV7_CYCLE_COUNTER)
786                 ret = pmnc & ARMV7_FLAG_C;
787         else if ((counter >= ARMV7_COUNTER0) && (counter <= ARMV7_COUNTER_LAST))
788                 ret = pmnc & ARMV7_FLAG_P(counter);
789         else
790                 pr_err("CPU%u checking wrong counter %d overflow status\n",
791                         smp_processor_id(), counter);
792
793         return ret;
794 }
795
796 static inline int armv7_pmnc_select_counter(unsigned int idx)
797 {
798         u32 val;
799
800         if ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST)) {
801                 pr_err("CPU%u selecting wrong PMNC counter"
802                         " %d\n", smp_processor_id(), idx);
803                 return -1;
804         }
805
806         val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
807         asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
808         isb();
809
810         return idx;
811 }
812
813 static inline u32 armv7pmu_read_counter(int idx)
814 {
815         unsigned long value = 0;
816
817         if (idx == ARMV7_CYCLE_COUNTER)
818                 asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value));
819         else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
820                 if (armv7_pmnc_select_counter(idx) == idx)
821                         asm volatile("mrc p15, 0, %0, c9, c13, 2"
822                                      : "=r" (value));
823         } else
824                 pr_err("CPU%u reading wrong counter %d\n",
825                         smp_processor_id(), idx);
826
827         return value;
828 }
829
830 static inline void armv7pmu_write_counter(int idx, u32 value)
831 {
832         if (idx == ARMV7_CYCLE_COUNTER)
833                 asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
834         else if ((idx >= ARMV7_COUNTER0) && (idx <= ARMV7_COUNTER_LAST)) {
835                 if (armv7_pmnc_select_counter(idx) == idx)
836                         asm volatile("mcr p15, 0, %0, c9, c13, 2"
837                                      : : "r" (value));
838         } else
839                 pr_err("CPU%u writing wrong counter %d\n",
840                         smp_processor_id(), idx);
841 }
842
843 static inline void armv7_pmnc_write_evtsel(unsigned int idx, u32 val)
844 {
845         if (armv7_pmnc_select_counter(idx) == idx) {
846                 val &= ARMV7_EVTSEL_MASK;
847                 asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
848         }
849 }
850
851 static inline u32 armv7_pmnc_enable_counter(unsigned int idx)
852 {
853         u32 val;
854
855         if ((idx != ARMV7_CYCLE_COUNTER) &&
856             ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
857                 pr_err("CPU%u enabling wrong PMNC counter"
858                         " %d\n", smp_processor_id(), idx);
859                 return -1;
860         }
861
862         if (idx == ARMV7_CYCLE_COUNTER)
863                 val = ARMV7_CNTENS_C;
864         else
865                 val = ARMV7_CNTENS_P(idx);
866
867         asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
868
869         return idx;
870 }
871
872 static inline u32 armv7_pmnc_disable_counter(unsigned int idx)
873 {
874         u32 val;
875
876
877         if ((idx != ARMV7_CYCLE_COUNTER) &&
878             ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
879                 pr_err("CPU%u disabling wrong PMNC counter"
880                         " %d\n", smp_processor_id(), idx);
881                 return -1;
882         }
883
884         if (idx == ARMV7_CYCLE_COUNTER)
885                 val = ARMV7_CNTENC_C;
886         else
887                 val = ARMV7_CNTENC_P(idx);
888
889         asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
890
891         return idx;
892 }
893
894 static inline u32 armv7_pmnc_enable_intens(unsigned int idx)
895 {
896         u32 val;
897
898         if ((idx != ARMV7_CYCLE_COUNTER) &&
899             ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
900                 pr_err("CPU%u enabling wrong PMNC counter"
901                         " interrupt enable %d\n", smp_processor_id(), idx);
902                 return -1;
903         }
904
905         if (idx == ARMV7_CYCLE_COUNTER)
906                 val = ARMV7_INTENS_C;
907         else
908                 val = ARMV7_INTENS_P(idx);
909
910         asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
911
912         return idx;
913 }
914
915 static inline u32 armv7_pmnc_disable_intens(unsigned int idx)
916 {
917         u32 val;
918
919         if ((idx != ARMV7_CYCLE_COUNTER) &&
920             ((idx < ARMV7_COUNTER0) || (idx > ARMV7_COUNTER_LAST))) {
921                 pr_err("CPU%u disabling wrong PMNC counter"
922                         " interrupt enable %d\n", smp_processor_id(), idx);
923                 return -1;
924         }
925
926         if (idx == ARMV7_CYCLE_COUNTER)
927                 val = ARMV7_INTENC_C;
928         else
929                 val = ARMV7_INTENC_P(idx);
930
931         asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val));
932
933         return idx;
934 }
935
936 static inline u32 armv7_pmnc_getreset_flags(void)
937 {
938         u32 val;
939
940         /* Read */
941         asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
942
943         /* Write to clear flags */
944         val &= ARMV7_FLAG_MASK;
945         asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
946
947         return val;
948 }
949
950 #ifdef DEBUG
951 static void armv7_pmnc_dump_regs(void)
952 {
953         u32 val;
954         unsigned int cnt;
955
956         printk(KERN_INFO "PMNC registers dump:\n");
957
958         asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
959         printk(KERN_INFO "PMNC  =0x%08x\n", val);
960
961         asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
962         printk(KERN_INFO "CNTENS=0x%08x\n", val);
963
964         asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
965         printk(KERN_INFO "INTENS=0x%08x\n", val);
966
967         asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
968         printk(KERN_INFO "FLAGS =0x%08x\n", val);
969
970         asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
971         printk(KERN_INFO "SELECT=0x%08x\n", val);
972
973         asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
974         printk(KERN_INFO "CCNT  =0x%08x\n", val);
975
976         for (cnt = ARMV7_COUNTER0; cnt < ARMV7_COUNTER_LAST; cnt++) {
977                 armv7_pmnc_select_counter(cnt);
978                 asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
979                 printk(KERN_INFO "CNT[%d] count =0x%08x\n",
980                         cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
981                 asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
982                 printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n",
983                         cnt-ARMV7_EVENT_CNT_TO_CNTx, val);
984         }
985 }
986 #endif
987
988 static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx)
989 {
990         unsigned long flags;
991
992         /*
993          * Enable counter and interrupt, and set the counter to count
994          * the event that we're interested in.
995          */
996         raw_spin_lock_irqsave(&pmu_lock, flags);
997
998         /*
999          * Disable counter
1000          */
1001         armv7_pmnc_disable_counter(idx);
1002
1003         /*
1004          * Set event (if destined for PMNx counters)
1005          * We don't need to set the event if it's a cycle count
1006          */
1007         if (idx != ARMV7_CYCLE_COUNTER)
1008                 armv7_pmnc_write_evtsel(idx, hwc->config_base);
1009
1010         /*
1011          * Enable interrupt for this counter
1012          */
1013         armv7_pmnc_enable_intens(idx);
1014
1015         /*
1016          * Enable counter
1017          */
1018         armv7_pmnc_enable_counter(idx);
1019
1020         raw_spin_unlock_irqrestore(&pmu_lock, flags);
1021 }
1022
1023 static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx)
1024 {
1025         unsigned long flags;
1026
1027         /*
1028          * Disable counter and interrupt
1029          */
1030         raw_spin_lock_irqsave(&pmu_lock, flags);
1031
1032         /*
1033          * Disable counter
1034          */
1035         armv7_pmnc_disable_counter(idx);
1036
1037         /*
1038          * Disable interrupt for this counter
1039          */
1040         armv7_pmnc_disable_intens(idx);
1041
1042         raw_spin_unlock_irqrestore(&pmu_lock, flags);
1043 }
1044
1045 static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev)
1046 {
1047         unsigned long pmnc;
1048         struct perf_sample_data data;
1049         struct cpu_hw_events *cpuc;
1050         struct pt_regs *regs;
1051         int idx;
1052
1053         /*
1054          * Get and reset the IRQ flags
1055          */
1056         pmnc = armv7_pmnc_getreset_flags();
1057
1058         /*
1059          * Did an overflow occur?
1060          */
1061         if (!armv7_pmnc_has_overflowed(pmnc))
1062                 return IRQ_NONE;
1063
1064         /*
1065          * Handle the counter(s) overflow(s)
1066          */
1067         regs = get_irq_regs();
1068
1069         perf_sample_data_init(&data, 0);
1070
1071         cpuc = &__get_cpu_var(cpu_hw_events);
1072         for (idx = 0; idx <= armpmu->num_events; ++idx) {
1073                 struct perf_event *event = cpuc->events[idx];
1074                 struct hw_perf_event *hwc;
1075
1076                 if (!test_bit(idx, cpuc->active_mask))
1077                         continue;
1078
1079                 /*
1080                  * We have a single interrupt for all counters. Check that
1081                  * each counter has overflowed before we process it.
1082                  */
1083                 if (!armv7_pmnc_counter_has_overflowed(pmnc, idx))
1084                         continue;
1085
1086                 hwc = &event->hw;
1087                 armpmu_event_update(event, hwc, idx, 1);
1088                 data.period = event->hw.last_period;
1089                 if (!armpmu_event_set_period(event, hwc, idx))
1090                         continue;
1091
1092                 if (perf_event_overflow(event, &data, regs))
1093                         armpmu->disable(hwc, idx);
1094         }
1095
1096         /*
1097          * Handle the pending perf events.
1098          *
1099          * Note: this call *must* be run with interrupts disabled. For
1100          * platforms that can have the PMU interrupts raised as an NMI, this
1101          * will not work.
1102          */
1103         irq_work_run();
1104
1105         return IRQ_HANDLED;
1106 }
1107
1108 static void armv7pmu_start(void)
1109 {
1110         unsigned long flags;
1111
1112         raw_spin_lock_irqsave(&pmu_lock, flags);
1113         /* Enable all counters */
1114         armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E);
1115         raw_spin_unlock_irqrestore(&pmu_lock, flags);
1116 }
1117
1118 static void armv7pmu_stop(void)
1119 {
1120         unsigned long flags;
1121
1122         raw_spin_lock_irqsave(&pmu_lock, flags);
1123         /* Disable all counters */
1124         armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E);
1125         raw_spin_unlock_irqrestore(&pmu_lock, flags);
1126 }
1127
1128 static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
1129                                   struct hw_perf_event *event)
1130 {
1131         int idx;
1132
1133         /* Always place a cycle counter into the cycle counter. */
1134         if (event->config_base == ARMV7_PERFCTR_CPU_CYCLES) {
1135                 if (test_and_set_bit(ARMV7_CYCLE_COUNTER, cpuc->used_mask))
1136                         return -EAGAIN;
1137
1138                 return ARMV7_CYCLE_COUNTER;
1139         } else {
1140                 /*
1141                  * For anything other than a cycle counter, try and use
1142                  * the events counters
1143                  */
1144                 for (idx = ARMV7_COUNTER0; idx <= armpmu->num_events; ++idx) {
1145                         if (!test_and_set_bit(idx, cpuc->used_mask))
1146                                 return idx;
1147                 }
1148
1149                 /* The counters are all in use. */
1150                 return -EAGAIN;
1151         }
1152 }
1153
1154 static void armv7pmu_reset(void *info)
1155 {
1156         u32 idx, nb_cnt = armpmu->num_events;
1157
1158         /* The counter and interrupt enable registers are unknown at reset. */
1159         for (idx = 1; idx < nb_cnt; ++idx)
1160                 armv7pmu_disable_event(NULL, idx);
1161
1162         /* Initialize & Reset PMNC: C and P bits */
1163         armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
1164 }
1165
1166 static struct arm_pmu armv7pmu = {
1167         .handle_irq             = armv7pmu_handle_irq,
1168         .enable                 = armv7pmu_enable_event,
1169         .disable                = armv7pmu_disable_event,
1170         .read_counter           = armv7pmu_read_counter,
1171         .write_counter          = armv7pmu_write_counter,
1172         .get_event_idx          = armv7pmu_get_event_idx,
1173         .start                  = armv7pmu_start,
1174         .stop                   = armv7pmu_stop,
1175         .reset                  = armv7pmu_reset,
1176         .raw_event_mask         = 0xFF,
1177         .max_period             = (1LLU << 32) - 1,
1178 };
1179
1180 static u32 __init armv7_read_num_pmnc_events(void)
1181 {
1182         u32 nb_cnt;
1183
1184         /* Read the nb of CNTx counters supported from PMNC */
1185         nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
1186
1187         /* Add the CPU cycles counter and return */
1188         return nb_cnt + 1;
1189 }
1190
1191 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
1192 {
1193         armv7pmu.id             = ARM_PERF_PMU_ID_CA8;
1194         armv7pmu.name           = "ARMv7 Cortex-A8";
1195         armv7pmu.cache_map      = &armv7_a8_perf_cache_map;
1196         armv7pmu.event_map      = &armv7_a8_perf_map;
1197         armv7pmu.num_events     = armv7_read_num_pmnc_events();
1198         return &armv7pmu;
1199 }
1200
1201 static const struct arm_pmu *__init armv7_a9_pmu_init(void)
1202 {
1203         armv7pmu.id             = ARM_PERF_PMU_ID_CA9;
1204         armv7pmu.name           = "ARMv7 Cortex-A9";
1205         armv7pmu.cache_map      = &armv7_a9_perf_cache_map;
1206         armv7pmu.event_map      = &armv7_a9_perf_map;
1207         armv7pmu.num_events     = armv7_read_num_pmnc_events();
1208         return &armv7pmu;
1209 }
1210
1211 static const struct arm_pmu *__init armv7_a5_pmu_init(void)
1212 {
1213         armv7pmu.id             = ARM_PERF_PMU_ID_CA5;
1214         armv7pmu.name           = "ARMv7 Cortex-A5";
1215         armv7pmu.cache_map      = &armv7_a5_perf_cache_map;
1216         armv7pmu.event_map      = &armv7_a5_perf_map;
1217         armv7pmu.num_events     = armv7_read_num_pmnc_events();
1218         return &armv7pmu;
1219 }
1220
1221 static const struct arm_pmu *__init armv7_a15_pmu_init(void)
1222 {
1223         armv7pmu.id             = ARM_PERF_PMU_ID_CA15;
1224         armv7pmu.name           = "ARMv7 Cortex-A15";
1225         armv7pmu.cache_map      = &armv7_a15_perf_cache_map;
1226         armv7pmu.event_map      = &armv7_a15_perf_map;
1227         armv7pmu.num_events     = armv7_read_num_pmnc_events();
1228         return &armv7pmu;
1229 }
1230 #else
1231 static const struct arm_pmu *__init armv7_a8_pmu_init(void)
1232 {
1233         return NULL;
1234 }
1235
1236 static const struct arm_pmu *__init armv7_a9_pmu_init(void)
1237 {
1238         return NULL;
1239 }
1240
1241 static const struct arm_pmu *__init armv7_a5_pmu_init(void)
1242 {
1243         return NULL;
1244 }
1245
1246 static const struct arm_pmu *__init armv7_a15_pmu_init(void)
1247 {
1248         return NULL;
1249 }
1250 #endif  /* CONFIG_CPU_V7 */