Linux Audio

Check our new training course

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