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