Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
perf_event_xscale.c
Go to the documentation of this file.
1 /*
2  * ARMv5 [xscale] Performance counter handling code.
3  *
4  * Copyright (C) 2010, ARM Ltd., Will Deacon <[email protected]>
5  *
6  * Based on the previous xscale OProfile code.
7  *
8  * There are two variants of the xscale PMU that we support:
9  * - xscale1pmu: 2 event counters and a cycle counter
10  * - xscale2pmu: 4 event counters and a cycle counter
11  * The two variants share event definitions, but have different
12  * PMU structures.
13  */
14 
15 #ifdef CONFIG_CPU_XSCALE
16 enum xscale_perf_types {
17  XSCALE_PERFCTR_ICACHE_MISS = 0x00,
18  XSCALE_PERFCTR_ICACHE_NO_DELIVER = 0x01,
19  XSCALE_PERFCTR_DATA_STALL = 0x02,
20  XSCALE_PERFCTR_ITLB_MISS = 0x03,
21  XSCALE_PERFCTR_DTLB_MISS = 0x04,
22  XSCALE_PERFCTR_BRANCH = 0x05,
23  XSCALE_PERFCTR_BRANCH_MISS = 0x06,
24  XSCALE_PERFCTR_INSTRUCTION = 0x07,
25  XSCALE_PERFCTR_DCACHE_FULL_STALL = 0x08,
26  XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG = 0x09,
27  XSCALE_PERFCTR_DCACHE_ACCESS = 0x0A,
28  XSCALE_PERFCTR_DCACHE_MISS = 0x0B,
29  XSCALE_PERFCTR_DCACHE_WRITE_BACK = 0x0C,
30  XSCALE_PERFCTR_PC_CHANGED = 0x0D,
31  XSCALE_PERFCTR_BCU_REQUEST = 0x10,
32  XSCALE_PERFCTR_BCU_FULL = 0x11,
33  XSCALE_PERFCTR_BCU_DRAIN = 0x12,
34  XSCALE_PERFCTR_BCU_ECC_NO_ELOG = 0x14,
35  XSCALE_PERFCTR_BCU_1_BIT_ERR = 0x15,
36  XSCALE_PERFCTR_RMW = 0x16,
37  /* XSCALE_PERFCTR_CCNT is not hardware defined */
38  XSCALE_PERFCTR_CCNT = 0xFE,
39  XSCALE_PERFCTR_UNUSED = 0xFF,
40 };
41 
42 enum xscale_counters {
43  XSCALE_CYCLE_COUNTER = 0,
44  XSCALE_COUNTER0,
45  XSCALE_COUNTER1,
46  XSCALE_COUNTER2,
47  XSCALE_COUNTER3,
48 };
49 
50 static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
51  [PERF_COUNT_HW_CPU_CYCLES] = XSCALE_PERFCTR_CCNT,
52  [PERF_COUNT_HW_INSTRUCTIONS] = XSCALE_PERFCTR_INSTRUCTION,
55  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
56  [PERF_COUNT_HW_BRANCH_MISSES] = XSCALE_PERFCTR_BRANCH_MISS,
58  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XSCALE_PERFCTR_ICACHE_NO_DELIVER,
60 };
61 
62 static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
65  [C(L1D)] = {
66  [C(OP_READ)] = {
67  [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
68  [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
69  },
70  [C(OP_WRITE)] = {
71  [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
72  [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
73  },
74  [C(OP_PREFETCH)] = {
75  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
76  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
77  },
78  },
79  [C(L1I)] = {
80  [C(OP_READ)] = {
81  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
82  [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
83  },
84  [C(OP_WRITE)] = {
85  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
86  [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
87  },
88  [C(OP_PREFETCH)] = {
89  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
90  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
91  },
92  },
93  [C(LL)] = {
94  [C(OP_READ)] = {
95  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
96  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
97  },
98  [C(OP_WRITE)] = {
99  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
100  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
101  },
102  [C(OP_PREFETCH)] = {
103  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
104  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
105  },
106  },
107  [C(DTLB)] = {
108  [C(OP_READ)] = {
109  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
110  [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
111  },
112  [C(OP_WRITE)] = {
113  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
114  [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
115  },
116  [C(OP_PREFETCH)] = {
117  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
118  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
119  },
120  },
121  [C(ITLB)] = {
122  [C(OP_READ)] = {
123  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
124  [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
125  },
126  [C(OP_WRITE)] = {
127  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
128  [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
129  },
130  [C(OP_PREFETCH)] = {
131  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
132  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
133  },
134  },
135  [C(BPU)] = {
136  [C(OP_READ)] = {
137  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
138  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
139  },
140  [C(OP_WRITE)] = {
141  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
142  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
143  },
144  [C(OP_PREFETCH)] = {
145  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
146  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
147  },
148  },
149  [C(NODE)] = {
150  [C(OP_READ)] = {
151  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
152  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
153  },
154  [C(OP_WRITE)] = {
155  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
156  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
157  },
158  [C(OP_PREFETCH)] = {
159  [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
160  [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
161  },
162  },
163 };
164 
165 #define XSCALE_PMU_ENABLE 0x001
166 #define XSCALE_PMN_RESET 0x002
167 #define XSCALE_CCNT_RESET 0x004
168 #define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET)
169 #define XSCALE_PMU_CNT64 0x008
170 
171 #define XSCALE1_OVERFLOWED_MASK 0x700
172 #define XSCALE1_CCOUNT_OVERFLOW 0x400
173 #define XSCALE1_COUNT0_OVERFLOW 0x100
174 #define XSCALE1_COUNT1_OVERFLOW 0x200
175 #define XSCALE1_CCOUNT_INT_EN 0x040
176 #define XSCALE1_COUNT0_INT_EN 0x010
177 #define XSCALE1_COUNT1_INT_EN 0x020
178 #define XSCALE1_COUNT0_EVT_SHFT 12
179 #define XSCALE1_COUNT0_EVT_MASK (0xff << XSCALE1_COUNT0_EVT_SHFT)
180 #define XSCALE1_COUNT1_EVT_SHFT 20
181 #define XSCALE1_COUNT1_EVT_MASK (0xff << XSCALE1_COUNT1_EVT_SHFT)
182 
183 static inline u32
184 xscale1pmu_read_pmnc(void)
185 {
186  u32 val;
187  asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
188  return val;
189 }
190 
191 static inline void
192 xscale1pmu_write_pmnc(u32 val)
193 {
194  /* upper 4bits and 7, 11 are write-as-0 */
195  val &= 0xffff77f;
196  asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
197 }
198 
199 static inline int
200 xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
201  enum xscale_counters counter)
202 {
203  int ret = 0;
204 
205  switch (counter) {
206  case XSCALE_CYCLE_COUNTER:
207  ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
208  break;
209  case XSCALE_COUNTER0:
210  ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
211  break;
212  case XSCALE_COUNTER1:
213  ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
214  break;
215  default:
216  WARN_ONCE(1, "invalid counter number (%d)\n", counter);
217  }
218 
219  return ret;
220 }
221 
222 static irqreturn_t
223 xscale1pmu_handle_irq(int irq_num, void *dev)
224 {
225  unsigned long pmnc;
226  struct perf_sample_data data;
227  struct pmu_hw_events *cpuc;
228  struct pt_regs *regs;
229  int idx;
230 
231  /*
232  * NOTE: there's an A stepping erratum that states if an overflow
233  * bit already exists and another occurs, the previous
234  * Overflow bit gets cleared. There's no workaround.
235  * Fixed in B stepping or later.
236  */
237  pmnc = xscale1pmu_read_pmnc();
238 
239  /*
240  * Write the value back to clear the overflow flags. Overflow
241  * flags remain in pmnc for use below. We also disable the PMU
242  * while we process the interrupt.
243  */
244  xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
245 
246  if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
247  return IRQ_NONE;
248 
249  regs = get_irq_regs();
250 
251  cpuc = &__get_cpu_var(cpu_hw_events);
252  for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
253  struct perf_event *event = cpuc->events[idx];
254  struct hw_perf_event *hwc;
255 
256  if (!event)
257  continue;
258 
259  if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
260  continue;
261 
262  hwc = &event->hw;
263  armpmu_event_update(event, hwc, idx);
264  perf_sample_data_init(&data, 0, hwc->last_period);
265  if (!armpmu_event_set_period(event, hwc, idx))
266  continue;
267 
268  if (perf_event_overflow(event, &data, regs))
269  cpu_pmu->disable(hwc, idx);
270  }
271 
272  irq_work_run();
273 
274  /*
275  * Re-enable the PMU.
276  */
277  pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
278  xscale1pmu_write_pmnc(pmnc);
279 
280  return IRQ_HANDLED;
281 }
282 
283 static void
284 xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
285 {
286  unsigned long val, mask, evt, flags;
287  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
288 
289  switch (idx) {
290  case XSCALE_CYCLE_COUNTER:
291  mask = 0;
292  evt = XSCALE1_CCOUNT_INT_EN;
293  break;
294  case XSCALE_COUNTER0:
295  mask = XSCALE1_COUNT0_EVT_MASK;
296  evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
297  XSCALE1_COUNT0_INT_EN;
298  break;
299  case XSCALE_COUNTER1:
300  mask = XSCALE1_COUNT1_EVT_MASK;
301  evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
302  XSCALE1_COUNT1_INT_EN;
303  break;
304  default:
305  WARN_ONCE(1, "invalid counter number (%d)\n", idx);
306  return;
307  }
308 
309  raw_spin_lock_irqsave(&events->pmu_lock, flags);
310  val = xscale1pmu_read_pmnc();
311  val &= ~mask;
312  val |= evt;
313  xscale1pmu_write_pmnc(val);
314  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
315 }
316 
317 static void
318 xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
319 {
320  unsigned long val, mask, evt, flags;
321  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
322 
323  switch (idx) {
324  case XSCALE_CYCLE_COUNTER:
325  mask = XSCALE1_CCOUNT_INT_EN;
326  evt = 0;
327  break;
328  case XSCALE_COUNTER0:
329  mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
330  evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
331  break;
332  case XSCALE_COUNTER1:
333  mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
334  evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
335  break;
336  default:
337  WARN_ONCE(1, "invalid counter number (%d)\n", idx);
338  return;
339  }
340 
341  raw_spin_lock_irqsave(&events->pmu_lock, flags);
342  val = xscale1pmu_read_pmnc();
343  val &= ~mask;
344  val |= evt;
345  xscale1pmu_write_pmnc(val);
346  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
347 }
348 
349 static int
350 xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
351  struct hw_perf_event *event)
352 {
353  if (XSCALE_PERFCTR_CCNT == event->config_base) {
354  if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
355  return -EAGAIN;
356 
357  return XSCALE_CYCLE_COUNTER;
358  } else {
359  if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask))
360  return XSCALE_COUNTER1;
361 
362  if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask))
363  return XSCALE_COUNTER0;
364 
365  return -EAGAIN;
366  }
367 }
368 
369 static void
370 xscale1pmu_start(void)
371 {
372  unsigned long flags, val;
373  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
374 
375  raw_spin_lock_irqsave(&events->pmu_lock, flags);
376  val = xscale1pmu_read_pmnc();
377  val |= XSCALE_PMU_ENABLE;
378  xscale1pmu_write_pmnc(val);
379  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
380 }
381 
382 static void
383 xscale1pmu_stop(void)
384 {
385  unsigned long flags, val;
386  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
387 
388  raw_spin_lock_irqsave(&events->pmu_lock, flags);
389  val = xscale1pmu_read_pmnc();
390  val &= ~XSCALE_PMU_ENABLE;
391  xscale1pmu_write_pmnc(val);
392  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
393 }
394 
395 static inline u32
396 xscale1pmu_read_counter(int counter)
397 {
398  u32 val = 0;
399 
400  switch (counter) {
401  case XSCALE_CYCLE_COUNTER:
402  asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
403  break;
404  case XSCALE_COUNTER0:
405  asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
406  break;
407  case XSCALE_COUNTER1:
408  asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
409  break;
410  }
411 
412  return val;
413 }
414 
415 static inline void
416 xscale1pmu_write_counter(int counter, u32 val)
417 {
418  switch (counter) {
419  case XSCALE_CYCLE_COUNTER:
420  asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
421  break;
422  case XSCALE_COUNTER0:
423  asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
424  break;
425  case XSCALE_COUNTER1:
426  asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
427  break;
428  }
429 }
430 
431 static int xscale_map_event(struct perf_event *event)
432 {
433  return armpmu_map_event(event, &xscale_perf_map,
434  &xscale_perf_cache_map, 0xFF);
435 }
436 
437 static struct arm_pmu xscale1pmu = {
438  .name = "xscale1",
439  .handle_irq = xscale1pmu_handle_irq,
440  .enable = xscale1pmu_enable_event,
441  .disable = xscale1pmu_disable_event,
442  .read_counter = xscale1pmu_read_counter,
443  .write_counter = xscale1pmu_write_counter,
444  .get_event_idx = xscale1pmu_get_event_idx,
445  .start = xscale1pmu_start,
446  .stop = xscale1pmu_stop,
447  .map_event = xscale_map_event,
448  .num_events = 3,
449  .max_period = (1LLU << 32) - 1,
450 };
451 
452 static struct arm_pmu *__devinit xscale1pmu_init(void)
453 {
454  return &xscale1pmu;
455 }
456 
457 #define XSCALE2_OVERFLOWED_MASK 0x01f
458 #define XSCALE2_CCOUNT_OVERFLOW 0x001
459 #define XSCALE2_COUNT0_OVERFLOW 0x002
460 #define XSCALE2_COUNT1_OVERFLOW 0x004
461 #define XSCALE2_COUNT2_OVERFLOW 0x008
462 #define XSCALE2_COUNT3_OVERFLOW 0x010
463 #define XSCALE2_CCOUNT_INT_EN 0x001
464 #define XSCALE2_COUNT0_INT_EN 0x002
465 #define XSCALE2_COUNT1_INT_EN 0x004
466 #define XSCALE2_COUNT2_INT_EN 0x008
467 #define XSCALE2_COUNT3_INT_EN 0x010
468 #define XSCALE2_COUNT0_EVT_SHFT 0
469 #define XSCALE2_COUNT0_EVT_MASK (0xff << XSCALE2_COUNT0_EVT_SHFT)
470 #define XSCALE2_COUNT1_EVT_SHFT 8
471 #define XSCALE2_COUNT1_EVT_MASK (0xff << XSCALE2_COUNT1_EVT_SHFT)
472 #define XSCALE2_COUNT2_EVT_SHFT 16
473 #define XSCALE2_COUNT2_EVT_MASK (0xff << XSCALE2_COUNT2_EVT_SHFT)
474 #define XSCALE2_COUNT3_EVT_SHFT 24
475 #define XSCALE2_COUNT3_EVT_MASK (0xff << XSCALE2_COUNT3_EVT_SHFT)
476 
477 static inline u32
478 xscale2pmu_read_pmnc(void)
479 {
480  u32 val;
481  asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
482  /* bits 1-2 and 4-23 are read-unpredictable */
483  return val & 0xff000009;
484 }
485 
486 static inline void
487 xscale2pmu_write_pmnc(u32 val)
488 {
489  /* bits 4-23 are write-as-0, 24-31 are write ignored */
490  val &= 0xf;
491  asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
492 }
493 
494 static inline u32
495 xscale2pmu_read_overflow_flags(void)
496 {
497  u32 val;
498  asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
499  return val;
500 }
501 
502 static inline void
503 xscale2pmu_write_overflow_flags(u32 val)
504 {
505  asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
506 }
507 
508 static inline u32
509 xscale2pmu_read_event_select(void)
510 {
511  u32 val;
512  asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
513  return val;
514 }
515 
516 static inline void
517 xscale2pmu_write_event_select(u32 val)
518 {
519  asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
520 }
521 
522 static inline u32
523 xscale2pmu_read_int_enable(void)
524 {
525  u32 val;
526  asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
527  return val;
528 }
529 
530 static void
531 xscale2pmu_write_int_enable(u32 val)
532 {
533  asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
534 }
535 
536 static inline int
537 xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
538  enum xscale_counters counter)
539 {
540  int ret = 0;
541 
542  switch (counter) {
543  case XSCALE_CYCLE_COUNTER:
544  ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
545  break;
546  case XSCALE_COUNTER0:
547  ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
548  break;
549  case XSCALE_COUNTER1:
550  ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
551  break;
552  case XSCALE_COUNTER2:
553  ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
554  break;
555  case XSCALE_COUNTER3:
556  ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
557  break;
558  default:
559  WARN_ONCE(1, "invalid counter number (%d)\n", counter);
560  }
561 
562  return ret;
563 }
564 
565 static irqreturn_t
566 xscale2pmu_handle_irq(int irq_num, void *dev)
567 {
568  unsigned long pmnc, of_flags;
569  struct perf_sample_data data;
570  struct pmu_hw_events *cpuc;
571  struct pt_regs *regs;
572  int idx;
573 
574  /* Disable the PMU. */
575  pmnc = xscale2pmu_read_pmnc();
576  xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
577 
578  /* Check the overflow flag register. */
579  of_flags = xscale2pmu_read_overflow_flags();
580  if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
581  return IRQ_NONE;
582 
583  /* Clear the overflow bits. */
584  xscale2pmu_write_overflow_flags(of_flags);
585 
586  regs = get_irq_regs();
587 
588  cpuc = &__get_cpu_var(cpu_hw_events);
589  for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
590  struct perf_event *event = cpuc->events[idx];
591  struct hw_perf_event *hwc;
592 
593  if (!event)
594  continue;
595 
596  if (!xscale2_pmnc_counter_has_overflowed(of_flags, idx))
597  continue;
598 
599  hwc = &event->hw;
600  armpmu_event_update(event, hwc, idx);
601  perf_sample_data_init(&data, 0, hwc->last_period);
602  if (!armpmu_event_set_period(event, hwc, idx))
603  continue;
604 
605  if (perf_event_overflow(event, &data, regs))
606  cpu_pmu->disable(hwc, idx);
607  }
608 
609  irq_work_run();
610 
611  /*
612  * Re-enable the PMU.
613  */
614  pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
615  xscale2pmu_write_pmnc(pmnc);
616 
617  return IRQ_HANDLED;
618 }
619 
620 static void
621 xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
622 {
623  unsigned long flags, ien, evtsel;
624  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
625 
626  ien = xscale2pmu_read_int_enable();
627  evtsel = xscale2pmu_read_event_select();
628 
629  switch (idx) {
630  case XSCALE_CYCLE_COUNTER:
631  ien |= XSCALE2_CCOUNT_INT_EN;
632  break;
633  case XSCALE_COUNTER0:
634  ien |= XSCALE2_COUNT0_INT_EN;
635  evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
636  evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
637  break;
638  case XSCALE_COUNTER1:
639  ien |= XSCALE2_COUNT1_INT_EN;
640  evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
641  evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
642  break;
643  case XSCALE_COUNTER2:
644  ien |= XSCALE2_COUNT2_INT_EN;
645  evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
646  evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
647  break;
648  case XSCALE_COUNTER3:
649  ien |= XSCALE2_COUNT3_INT_EN;
650  evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
651  evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
652  break;
653  default:
654  WARN_ONCE(1, "invalid counter number (%d)\n", idx);
655  return;
656  }
657 
658  raw_spin_lock_irqsave(&events->pmu_lock, flags);
659  xscale2pmu_write_event_select(evtsel);
660  xscale2pmu_write_int_enable(ien);
661  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
662 }
663 
664 static void
665 xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
666 {
667  unsigned long flags, ien, evtsel, of_flags;
668  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
669 
670  ien = xscale2pmu_read_int_enable();
671  evtsel = xscale2pmu_read_event_select();
672 
673  switch (idx) {
674  case XSCALE_CYCLE_COUNTER:
675  ien &= ~XSCALE2_CCOUNT_INT_EN;
676  of_flags = XSCALE2_CCOUNT_OVERFLOW;
677  break;
678  case XSCALE_COUNTER0:
679  ien &= ~XSCALE2_COUNT0_INT_EN;
680  evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
681  evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
682  of_flags = XSCALE2_COUNT0_OVERFLOW;
683  break;
684  case XSCALE_COUNTER1:
685  ien &= ~XSCALE2_COUNT1_INT_EN;
686  evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
687  evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
688  of_flags = XSCALE2_COUNT1_OVERFLOW;
689  break;
690  case XSCALE_COUNTER2:
691  ien &= ~XSCALE2_COUNT2_INT_EN;
692  evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
693  evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
694  of_flags = XSCALE2_COUNT2_OVERFLOW;
695  break;
696  case XSCALE_COUNTER3:
697  ien &= ~XSCALE2_COUNT3_INT_EN;
698  evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
699  evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
700  of_flags = XSCALE2_COUNT3_OVERFLOW;
701  break;
702  default:
703  WARN_ONCE(1, "invalid counter number (%d)\n", idx);
704  return;
705  }
706 
707  raw_spin_lock_irqsave(&events->pmu_lock, flags);
708  xscale2pmu_write_event_select(evtsel);
709  xscale2pmu_write_int_enable(ien);
710  xscale2pmu_write_overflow_flags(of_flags);
711  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
712 }
713 
714 static int
715 xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
716  struct hw_perf_event *event)
717 {
718  int idx = xscale1pmu_get_event_idx(cpuc, event);
719  if (idx >= 0)
720  goto out;
721 
722  if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
723  idx = XSCALE_COUNTER3;
724  else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
725  idx = XSCALE_COUNTER2;
726 out:
727  return idx;
728 }
729 
730 static void
731 xscale2pmu_start(void)
732 {
733  unsigned long flags, val;
734  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
735 
736  raw_spin_lock_irqsave(&events->pmu_lock, flags);
737  val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
738  val |= XSCALE_PMU_ENABLE;
739  xscale2pmu_write_pmnc(val);
740  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
741 }
742 
743 static void
744 xscale2pmu_stop(void)
745 {
746  unsigned long flags, val;
747  struct pmu_hw_events *events = cpu_pmu->get_hw_events();
748 
749  raw_spin_lock_irqsave(&events->pmu_lock, flags);
750  val = xscale2pmu_read_pmnc();
751  val &= ~XSCALE_PMU_ENABLE;
752  xscale2pmu_write_pmnc(val);
753  raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
754 }
755 
756 static inline u32
757 xscale2pmu_read_counter(int counter)
758 {
759  u32 val = 0;
760 
761  switch (counter) {
762  case XSCALE_CYCLE_COUNTER:
763  asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
764  break;
765  case XSCALE_COUNTER0:
766  asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
767  break;
768  case XSCALE_COUNTER1:
769  asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
770  break;
771  case XSCALE_COUNTER2:
772  asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
773  break;
774  case XSCALE_COUNTER3:
775  asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
776  break;
777  }
778 
779  return val;
780 }
781 
782 static inline void
783 xscale2pmu_write_counter(int counter, u32 val)
784 {
785  switch (counter) {
786  case XSCALE_CYCLE_COUNTER:
787  asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
788  break;
789  case XSCALE_COUNTER0:
790  asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
791  break;
792  case XSCALE_COUNTER1:
793  asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
794  break;
795  case XSCALE_COUNTER2:
796  asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
797  break;
798  case XSCALE_COUNTER3:
799  asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
800  break;
801  }
802 }
803 
804 static struct arm_pmu xscale2pmu = {
805  .name = "xscale2",
806  .handle_irq = xscale2pmu_handle_irq,
807  .enable = xscale2pmu_enable_event,
808  .disable = xscale2pmu_disable_event,
809  .read_counter = xscale2pmu_read_counter,
810  .write_counter = xscale2pmu_write_counter,
811  .get_event_idx = xscale2pmu_get_event_idx,
812  .start = xscale2pmu_start,
813  .stop = xscale2pmu_stop,
814  .map_event = xscale_map_event,
815  .num_events = 5,
816  .max_period = (1LLU << 32) - 1,
817 };
818 
819 static struct arm_pmu *__devinit xscale2pmu_init(void)
820 {
821  return &xscale2pmu;
822 }
823 #else
824 static struct arm_pmu *__devinit xscale1pmu_init(void)
825 {
826  return NULL;
827 }
828 
829 static struct arm_pmu *__devinit xscale2pmu_init(void)
830 {
831  return NULL;
832 }
833 #endif /* CONFIG_CPU_XSCALE */