Linux Audio

Check our new training course

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