2
* ARMv5 [xscale] Performance counter handling code.
4
* Copyright (C) 2010, ARM Ltd., Will Deacon <will.deacon@arm.com>
6
* Based on the previous xscale OProfile code.
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
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,
42
enum xscale_counters {
43
XSCALE_CYCLE_COUNTER = 1,
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,
53
[PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
54
[PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
55
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
56
[PERF_COUNT_HW_BRANCH_MISSES] = XSCALE_PERFCTR_BRANCH_MISS,
57
[PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED,
60
static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
61
[PERF_COUNT_HW_CACHE_OP_MAX]
62
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
65
[C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
66
[C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
69
[C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
70
[C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
73
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
74
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
79
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
80
[C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
83
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
84
[C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
87
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
88
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
93
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
94
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
97
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
98
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
101
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
102
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
107
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
108
[C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
111
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
112
[C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
115
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
116
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
121
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
122
[C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
125
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
126
[C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
129
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
130
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
135
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
136
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
139
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
140
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
143
[C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
144
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
149
#define XSCALE_PMU_ENABLE 0x001
150
#define XSCALE_PMN_RESET 0x002
151
#define XSCALE_CCNT_RESET 0x004
152
#define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET)
153
#define XSCALE_PMU_CNT64 0x008
155
#define XSCALE1_OVERFLOWED_MASK 0x700
156
#define XSCALE1_CCOUNT_OVERFLOW 0x400
157
#define XSCALE1_COUNT0_OVERFLOW 0x100
158
#define XSCALE1_COUNT1_OVERFLOW 0x200
159
#define XSCALE1_CCOUNT_INT_EN 0x040
160
#define XSCALE1_COUNT0_INT_EN 0x010
161
#define XSCALE1_COUNT1_INT_EN 0x020
162
#define XSCALE1_COUNT0_EVT_SHFT 12
163
#define XSCALE1_COUNT0_EVT_MASK (0xff << XSCALE1_COUNT0_EVT_SHFT)
164
#define XSCALE1_COUNT1_EVT_SHFT 20
165
#define XSCALE1_COUNT1_EVT_MASK (0xff << XSCALE1_COUNT1_EVT_SHFT)
168
xscale1pmu_read_pmnc(void)
171
asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
176
xscale1pmu_write_pmnc(u32 val)
178
/* upper 4bits and 7, 11 are write-as-0 */
180
asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
184
xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
185
enum xscale_counters counter)
190
case XSCALE_CYCLE_COUNTER:
191
ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
193
case XSCALE_COUNTER0:
194
ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
196
case XSCALE_COUNTER1:
197
ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
200
WARN_ONCE(1, "invalid counter number (%d)\n", counter);
207
xscale1pmu_handle_irq(int irq_num, void *dev)
210
struct perf_sample_data data;
211
struct cpu_hw_events *cpuc;
212
struct pt_regs *regs;
216
* NOTE: there's an A stepping erratum that states if an overflow
217
* bit already exists and another occurs, the previous
218
* Overflow bit gets cleared. There's no workaround.
219
* Fixed in B stepping or later.
221
pmnc = xscale1pmu_read_pmnc();
224
* Write the value back to clear the overflow flags. Overflow
225
* flags remain in pmnc for use below. We also disable the PMU
226
* while we process the interrupt.
228
xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
230
if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
233
regs = get_irq_regs();
235
perf_sample_data_init(&data, 0);
237
cpuc = &__get_cpu_var(cpu_hw_events);
238
for (idx = 0; idx <= armpmu->num_events; ++idx) {
239
struct perf_event *event = cpuc->events[idx];
240
struct hw_perf_event *hwc;
242
if (!test_bit(idx, cpuc->active_mask))
245
if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
249
armpmu_event_update(event, hwc, idx);
250
data.period = event->hw.last_period;
251
if (!armpmu_event_set_period(event, hwc, idx))
254
if (perf_event_overflow(event, 0, &data, regs))
255
armpmu->disable(hwc, idx);
263
pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
264
xscale1pmu_write_pmnc(pmnc);
270
xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx)
272
unsigned long val, mask, evt, flags;
275
case XSCALE_CYCLE_COUNTER:
277
evt = XSCALE1_CCOUNT_INT_EN;
279
case XSCALE_COUNTER0:
280
mask = XSCALE1_COUNT0_EVT_MASK;
281
evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
282
XSCALE1_COUNT0_INT_EN;
284
case XSCALE_COUNTER1:
285
mask = XSCALE1_COUNT1_EVT_MASK;
286
evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
287
XSCALE1_COUNT1_INT_EN;
290
WARN_ONCE(1, "invalid counter number (%d)\n", idx);
294
raw_spin_lock_irqsave(&pmu_lock, flags);
295
val = xscale1pmu_read_pmnc();
298
xscale1pmu_write_pmnc(val);
299
raw_spin_unlock_irqrestore(&pmu_lock, flags);
303
xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx)
305
unsigned long val, mask, evt, flags;
308
case XSCALE_CYCLE_COUNTER:
309
mask = XSCALE1_CCOUNT_INT_EN;
312
case XSCALE_COUNTER0:
313
mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
314
evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
316
case XSCALE_COUNTER1:
317
mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
318
evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
321
WARN_ONCE(1, "invalid counter number (%d)\n", idx);
325
raw_spin_lock_irqsave(&pmu_lock, flags);
326
val = xscale1pmu_read_pmnc();
329
xscale1pmu_write_pmnc(val);
330
raw_spin_unlock_irqrestore(&pmu_lock, flags);
334
xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc,
335
struct hw_perf_event *event)
337
if (XSCALE_PERFCTR_CCNT == event->config_base) {
338
if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
341
return XSCALE_CYCLE_COUNTER;
343
if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask))
344
return XSCALE_COUNTER1;
346
if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask))
347
return XSCALE_COUNTER0;
354
xscale1pmu_start(void)
356
unsigned long flags, val;
358
raw_spin_lock_irqsave(&pmu_lock, flags);
359
val = xscale1pmu_read_pmnc();
360
val |= XSCALE_PMU_ENABLE;
361
xscale1pmu_write_pmnc(val);
362
raw_spin_unlock_irqrestore(&pmu_lock, flags);
366
xscale1pmu_stop(void)
368
unsigned long flags, val;
370
raw_spin_lock_irqsave(&pmu_lock, flags);
371
val = xscale1pmu_read_pmnc();
372
val &= ~XSCALE_PMU_ENABLE;
373
xscale1pmu_write_pmnc(val);
374
raw_spin_unlock_irqrestore(&pmu_lock, flags);
378
xscale1pmu_read_counter(int counter)
383
case XSCALE_CYCLE_COUNTER:
384
asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
386
case XSCALE_COUNTER0:
387
asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
389
case XSCALE_COUNTER1:
390
asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
398
xscale1pmu_write_counter(int counter, u32 val)
401
case XSCALE_CYCLE_COUNTER:
402
asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
404
case XSCALE_COUNTER0:
405
asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
407
case XSCALE_COUNTER1:
408
asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
413
static const struct arm_pmu xscale1pmu = {
414
.id = ARM_PERF_PMU_ID_XSCALE1,
416
.handle_irq = xscale1pmu_handle_irq,
417
.enable = xscale1pmu_enable_event,
418
.disable = xscale1pmu_disable_event,
419
.read_counter = xscale1pmu_read_counter,
420
.write_counter = xscale1pmu_write_counter,
421
.get_event_idx = xscale1pmu_get_event_idx,
422
.start = xscale1pmu_start,
423
.stop = xscale1pmu_stop,
424
.cache_map = &xscale_perf_cache_map,
425
.event_map = &xscale_perf_map,
426
.raw_event_mask = 0xFF,
428
.max_period = (1LLU << 32) - 1,
431
static const struct arm_pmu *__init xscale1pmu_init(void)
436
#define XSCALE2_OVERFLOWED_MASK 0x01f
437
#define XSCALE2_CCOUNT_OVERFLOW 0x001
438
#define XSCALE2_COUNT0_OVERFLOW 0x002
439
#define XSCALE2_COUNT1_OVERFLOW 0x004
440
#define XSCALE2_COUNT2_OVERFLOW 0x008
441
#define XSCALE2_COUNT3_OVERFLOW 0x010
442
#define XSCALE2_CCOUNT_INT_EN 0x001
443
#define XSCALE2_COUNT0_INT_EN 0x002
444
#define XSCALE2_COUNT1_INT_EN 0x004
445
#define XSCALE2_COUNT2_INT_EN 0x008
446
#define XSCALE2_COUNT3_INT_EN 0x010
447
#define XSCALE2_COUNT0_EVT_SHFT 0
448
#define XSCALE2_COUNT0_EVT_MASK (0xff << XSCALE2_COUNT0_EVT_SHFT)
449
#define XSCALE2_COUNT1_EVT_SHFT 8
450
#define XSCALE2_COUNT1_EVT_MASK (0xff << XSCALE2_COUNT1_EVT_SHFT)
451
#define XSCALE2_COUNT2_EVT_SHFT 16
452
#define XSCALE2_COUNT2_EVT_MASK (0xff << XSCALE2_COUNT2_EVT_SHFT)
453
#define XSCALE2_COUNT3_EVT_SHFT 24
454
#define XSCALE2_COUNT3_EVT_MASK (0xff << XSCALE2_COUNT3_EVT_SHFT)
457
xscale2pmu_read_pmnc(void)
460
asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
461
/* bits 1-2 and 4-23 are read-unpredictable */
462
return val & 0xff000009;
466
xscale2pmu_write_pmnc(u32 val)
468
/* bits 4-23 are write-as-0, 24-31 are write ignored */
470
asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
474
xscale2pmu_read_overflow_flags(void)
477
asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
482
xscale2pmu_write_overflow_flags(u32 val)
484
asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
488
xscale2pmu_read_event_select(void)
491
asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
496
xscale2pmu_write_event_select(u32 val)
498
asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
502
xscale2pmu_read_int_enable(void)
505
asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
510
xscale2pmu_write_int_enable(u32 val)
512
asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
516
xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
517
enum xscale_counters counter)
522
case XSCALE_CYCLE_COUNTER:
523
ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
525
case XSCALE_COUNTER0:
526
ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
528
case XSCALE_COUNTER1:
529
ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
531
case XSCALE_COUNTER2:
532
ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
534
case XSCALE_COUNTER3:
535
ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
538
WARN_ONCE(1, "invalid counter number (%d)\n", counter);
545
xscale2pmu_handle_irq(int irq_num, void *dev)
547
unsigned long pmnc, of_flags;
548
struct perf_sample_data data;
549
struct cpu_hw_events *cpuc;
550
struct pt_regs *regs;
553
/* Disable the PMU. */
554
pmnc = xscale2pmu_read_pmnc();
555
xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
557
/* Check the overflow flag register. */
558
of_flags = xscale2pmu_read_overflow_flags();
559
if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
562
/* Clear the overflow bits. */
563
xscale2pmu_write_overflow_flags(of_flags);
565
regs = get_irq_regs();
567
perf_sample_data_init(&data, 0);
569
cpuc = &__get_cpu_var(cpu_hw_events);
570
for (idx = 0; idx <= armpmu->num_events; ++idx) {
571
struct perf_event *event = cpuc->events[idx];
572
struct hw_perf_event *hwc;
574
if (!test_bit(idx, cpuc->active_mask))
577
if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx))
581
armpmu_event_update(event, hwc, idx);
582
data.period = event->hw.last_period;
583
if (!armpmu_event_set_period(event, hwc, idx))
586
if (perf_event_overflow(event, 0, &data, regs))
587
armpmu->disable(hwc, idx);
595
pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
596
xscale2pmu_write_pmnc(pmnc);
602
xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx)
604
unsigned long flags, ien, evtsel;
606
ien = xscale2pmu_read_int_enable();
607
evtsel = xscale2pmu_read_event_select();
610
case XSCALE_CYCLE_COUNTER:
611
ien |= XSCALE2_CCOUNT_INT_EN;
613
case XSCALE_COUNTER0:
614
ien |= XSCALE2_COUNT0_INT_EN;
615
evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
616
evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
618
case XSCALE_COUNTER1:
619
ien |= XSCALE2_COUNT1_INT_EN;
620
evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
621
evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
623
case XSCALE_COUNTER2:
624
ien |= XSCALE2_COUNT2_INT_EN;
625
evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
626
evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
628
case XSCALE_COUNTER3:
629
ien |= XSCALE2_COUNT3_INT_EN;
630
evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
631
evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
634
WARN_ONCE(1, "invalid counter number (%d)\n", idx);
638
raw_spin_lock_irqsave(&pmu_lock, flags);
639
xscale2pmu_write_event_select(evtsel);
640
xscale2pmu_write_int_enable(ien);
641
raw_spin_unlock_irqrestore(&pmu_lock, flags);
645
xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx)
647
unsigned long flags, ien, evtsel;
649
ien = xscale2pmu_read_int_enable();
650
evtsel = xscale2pmu_read_event_select();
653
case XSCALE_CYCLE_COUNTER:
654
ien &= ~XSCALE2_CCOUNT_INT_EN;
656
case XSCALE_COUNTER0:
657
ien &= ~XSCALE2_COUNT0_INT_EN;
658
evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
659
evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
661
case XSCALE_COUNTER1:
662
ien &= ~XSCALE2_COUNT1_INT_EN;
663
evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
664
evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
666
case XSCALE_COUNTER2:
667
ien &= ~XSCALE2_COUNT2_INT_EN;
668
evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
669
evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
671
case XSCALE_COUNTER3:
672
ien &= ~XSCALE2_COUNT3_INT_EN;
673
evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
674
evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
677
WARN_ONCE(1, "invalid counter number (%d)\n", idx);
681
raw_spin_lock_irqsave(&pmu_lock, flags);
682
xscale2pmu_write_event_select(evtsel);
683
xscale2pmu_write_int_enable(ien);
684
raw_spin_unlock_irqrestore(&pmu_lock, flags);
688
xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc,
689
struct hw_perf_event *event)
691
int idx = xscale1pmu_get_event_idx(cpuc, event);
695
if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
696
idx = XSCALE_COUNTER3;
697
else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
698
idx = XSCALE_COUNTER2;
704
xscale2pmu_start(void)
706
unsigned long flags, val;
708
raw_spin_lock_irqsave(&pmu_lock, flags);
709
val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
710
val |= XSCALE_PMU_ENABLE;
711
xscale2pmu_write_pmnc(val);
712
raw_spin_unlock_irqrestore(&pmu_lock, flags);
716
xscale2pmu_stop(void)
718
unsigned long flags, val;
720
raw_spin_lock_irqsave(&pmu_lock, flags);
721
val = xscale2pmu_read_pmnc();
722
val &= ~XSCALE_PMU_ENABLE;
723
xscale2pmu_write_pmnc(val);
724
raw_spin_unlock_irqrestore(&pmu_lock, flags);
728
xscale2pmu_read_counter(int counter)
733
case XSCALE_CYCLE_COUNTER:
734
asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
736
case XSCALE_COUNTER0:
737
asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
739
case XSCALE_COUNTER1:
740
asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
742
case XSCALE_COUNTER2:
743
asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
745
case XSCALE_COUNTER3:
746
asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
754
xscale2pmu_write_counter(int counter, u32 val)
757
case XSCALE_CYCLE_COUNTER:
758
asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
760
case XSCALE_COUNTER0:
761
asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
763
case XSCALE_COUNTER1:
764
asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
766
case XSCALE_COUNTER2:
767
asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
769
case XSCALE_COUNTER3:
770
asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
775
static const struct arm_pmu xscale2pmu = {
776
.id = ARM_PERF_PMU_ID_XSCALE2,
778
.handle_irq = xscale2pmu_handle_irq,
779
.enable = xscale2pmu_enable_event,
780
.disable = xscale2pmu_disable_event,
781
.read_counter = xscale2pmu_read_counter,
782
.write_counter = xscale2pmu_write_counter,
783
.get_event_idx = xscale2pmu_get_event_idx,
784
.start = xscale2pmu_start,
785
.stop = xscale2pmu_stop,
786
.cache_map = &xscale_perf_cache_map,
787
.event_map = &xscale_perf_map,
788
.raw_event_mask = 0xFF,
790
.max_period = (1LLU << 32) - 1,
793
static const struct arm_pmu *__init xscale2pmu_init(void)
798
static const struct arm_pmu *__init xscale1pmu_init(void)
803
static const struct arm_pmu *__init xscale2pmu_init(void)
807
#endif /* CONFIG_CPU_XSCALE */