summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/oprofile-0.9.3.armv7.diff
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap2-git/beagleboard/oprofile-0.9.3.armv7.diff
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap2-git/beagleboard/oprofile-0.9.3.armv7.diff')
-rw-r--r--meta/recipes-kernel/linux/linux-omap2-git/beagleboard/oprofile-0.9.3.armv7.diff611
1 files changed, 611 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/oprofile-0.9.3.armv7.diff b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/oprofile-0.9.3.armv7.diff
new file mode 100644
index 0000000000..dbc11fbe7d
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap2-git/beagleboard/oprofile-0.9.3.armv7.diff
@@ -0,0 +1,611 @@
1Hi,
2
3This patch adds Oprofile support on ARMv7, using the PMNC unit.
4Tested on OMAP3430 SDP.
5
6Feedback and comments are welcome.
7
8The patch to user space components is attached for reference. It i applies
9against version 0.9.3 of oprofile source
10(http://prdownloads.sourceforge.net/oprofile/oprofile-0.9.3.tar.gz).
11
12Regards,
13Jean.
14
15---
16
17From: Jean Pihet <jpihet@mvista.com>
18Date: Tue, 6 May 2008 17:21:44 +0200
19Subject: [PATCH] ARM: Add ARMv7 oprofile support
20
21Add ARMv7 Oprofile support to kernel
22
23Signed-off-by: Jean Pihet <jpihet@mvista.com>
24---
25
26diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
27index c60a27d..60b50a0 100644
28--- a/arch/arm/Kconfig
29+++ b/arch/arm/Kconfig
30@@ -161,6 +161,11 @@ config OPROFILE_MPCORE
31 config OPROFILE_ARM11_CORE
32 bool
33
34+config OPROFILE_ARMV7
35+ def_bool y
36+ depends on CPU_V7 && !SMP
37+ bool
38+
39 endif
40
41 config VECTORS_BASE
42diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile
43index e61d0cc..88e31f5 100644
44--- a/arch/arm/oprofile/Makefile
45+++ b/arch/arm/oprofile/Makefile
46@@ -11,3 +11,4 @@ oprofile-$(CONFIG_CPU_XSCALE) += op_model_xscale.o
47 oprofile-$(CONFIG_OPROFILE_ARM11_CORE) += op_model_arm11_core.o
48 oprofile-$(CONFIG_OPROFILE_ARMV6) += op_model_v6.o
49 oprofile-$(CONFIG_OPROFILE_MPCORE) += op_model_mpcore.o
50+oprofile-$(CONFIG_OPROFILE_ARMV7) += op_model_v7.o
51diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
52index 0a5cf3a..3fcd752 100644
53--- a/arch/arm/oprofile/common.c
54+++ b/arch/arm/oprofile/common.c
55@@ -145,6 +145,10 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
56 spec = &op_mpcore_spec;
57 #endif
58
59+#ifdef CONFIG_OPROFILE_ARMV7
60+ spec = &op_armv7_spec;
61+#endif
62+
63 if (spec) {
64 ret = spec->init();
65 if (ret < 0)
66diff --git a/arch/arm/oprofile/op_arm_model.h
67b/arch/arm/oprofile/op_arm_model.h
68index 4899c62..8c4e4f6 100644
69--- a/arch/arm/oprofile/op_arm_model.h
70+++ b/arch/arm/oprofile/op_arm_model.h
71@@ -26,6 +26,7 @@ extern struct op_arm_model_spec op_xscale_spec;
72
73 extern struct op_arm_model_spec op_armv6_spec;
74 extern struct op_arm_model_spec op_mpcore_spec;
75+extern struct op_arm_model_spec op_armv7_spec;
76
77 extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);
78
79diff --git a/arch/arm/oprofile/op_model_v7.c b/arch/arm/oprofile/op_model_v7.c
80new file mode 100644
81index 0000000..a159bc1
82--- /dev/null
83+++ b/arch/arm/oprofile/op_model_v7.c
84@@ -0,0 +1,407 @@
85+/**
86+ * @file op_model_v7.c
87+ * ARM V7 (Cortex A8) Event Monitor Driver
88+ *
89+ * @remark Copyright 2008 Jean Pihet <jpihet@mvista.com>
90+ * @remark Copyright 2004 ARM SMP Development Team
91+ */
92+#include <linux/types.h>
93+#include <linux/errno.h>
94+#include <linux/oprofile.h>
95+#include <linux/interrupt.h>
96+#include <linux/irq.h>
97+#include <linux/smp.h>
98+
99+#include "op_counter.h"
100+#include "op_arm_model.h"
101+#include "op_model_v7.h"
102+
103+/* #define DEBUG */
104+
105+
106+/*
107+ * ARM V7 PMNC support
108+ */
109+
110+static u32 cnt_en[CNTMAX];
111+
112+static inline void armv7_pmnc_write(u32 val)
113+{
114+ val &= PMNC_MASK;
115+ asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (val));
116+}
117+
118+static inline u32 armv7_pmnc_read(void)
119+{
120+ u32 val;
121+
122+ asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
123+ return val;
124+}
125+
126+static inline u32 armv7_pmnc_enable_counter(unsigned int cnt)
127+{
128+ u32 val;
129+
130+ if (cnt >= CNTMAX) {
131+ printk(KERN_ERR "oprofile: CPU%u enabling wrong PMNC counter"
132+ " %d\n", smp_processor_id(), cnt);
133+ return -1;
134+ }
135+
136+ if (cnt == CCNT)
137+ val = CNTENS_C;
138+ else
139+ val = (1 << (cnt - CNT0));
140+
141+ val &= CNTENS_MASK;
142+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
143+
144+ return cnt;
145+}
146+
147+static inline u32 armv7_pmnc_disable_counter(unsigned int cnt)
148+{
149+ u32 val;
150+
151+ if (cnt >= CNTMAX) {
152+ printk(KERN_ERR "oprofile: CPU%u disabling wrong PMNC counter"
153+ " %d\n", smp_processor_id(), cnt);
154+ return -1;
155+ }
156+
157+ if (cnt == CCNT)
158+ val = CNTENC_C;
159+ else
160+ val = (1 << (cnt - CNT0));
161+
162+ val &= CNTENC_MASK;
163+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
164+
165+ return cnt;
166+}
167+
168+static inline u32 armv7_pmnc_enable_intens(unsigned int cnt)
169+{
170+ u32 val;
171+
172+ if (cnt >= CNTMAX) {
173+ printk(KERN_ERR "oprofile: CPU%u enabling wrong PMNC counter"
174+ " interrupt enable %d\n", smp_processor_id(), cnt);
175+ return -1;
176+ }
177+
178+ if (cnt == CCNT)
179+ val = INTENS_C;
180+ else
181+ val = (1 << (cnt - CNT0));
182+
183+ val &= INTENS_MASK;
184+ asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
185+
186+ return cnt;
187+}
188+
189+static inline u32 armv7_pmnc_getreset_flags(void)
190+{
191+ u32 val;
192+
193+ /* Read */
194+ asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
195+
196+ /* Write to clear flags */
197+ val &= FLAG_MASK;
198+ asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
199+
200+ return val;
201+}
202+
203+static inline int armv7_pmnc_select_counter(unsigned int cnt)
204+{
205+ u32 val;
206+
207+ if ((cnt == CCNT) || (cnt >= CNTMAX)) {
208+ printk(KERN_ERR "oprofile: CPU%u selecting wrong PMNC counteri"
209+ " %d\n", smp_processor_id(), cnt);
210+ return -1;
211+ }
212+
213+ val = (cnt - CNT0) & SELECT_MASK;
214+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
215+
216+ return cnt;
217+}
218+
219+static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val)
220+{
221+ if (armv7_pmnc_select_counter(cnt) == cnt) {
222+ val &= EVTSEL_MASK;
223+ asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
224+ }
225+}
226+
227+static void armv7_pmnc_reset_counter(unsigned int cnt)
228+{
229+ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt);
230+ u32 val = -(u32)counter_config[cpu_cnt].count;
231+
232+ switch (cnt) {
233+ case CCNT:
234+ armv7_pmnc_disable_counter(cnt);
235+
236+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (val));
237+
238+ if (cnt_en[cnt] != 0)
239+ armv7_pmnc_enable_counter(cnt);
240+
241+ break;
242+
243+ case CNT0:
244+ case CNT1:
245+ case CNT2:
246+ case CNT3:
247+ armv7_pmnc_disable_counter(cnt);
248+
249+ if (armv7_pmnc_select_counter(cnt) == cnt)
250+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val));
251+
252+ if (cnt_en[cnt] != 0)
253+ armv7_pmnc_enable_counter(cnt);
254+
255+ break;
256+
257+ default:
258+ printk(KERN_ERR "oprofile: CPU%u resetting wrong PMNC counter"
259+ " %d\n", smp_processor_id(), cnt);
260+ break;
261+ }
262+}
263+
264+int armv7_setup_pmnc(void)
265+{
266+ unsigned int cnt;
267+
268+ if (armv7_pmnc_read() & PMNC_E) {
269+ printk(KERN_ERR "oprofile: CPU%u PMNC still enabled when setup"
270+ " new event counter.\n", smp_processor_id());
271+ return -EBUSY;
272+ }
273+
274+ /*
275+ * Initialize & Reset PMNC: C bit, D bit and P bit.
276+ * Note: Using a slower count for CCNT (D bit: divide by 64) results
277+ * in a more stable system
278+ */
279+ armv7_pmnc_write(PMNC_P | PMNC_C | PMNC_D);
280+
281+
282+ for (cnt = CCNT; cnt < CNTMAX; cnt++) {
283+ unsigned long event;
284+ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt);
285+
286+ /*
287+ * Disable counter
288+ */
289+ armv7_pmnc_disable_counter(cnt);
290+ cnt_en[cnt] = 0;
291+
292+ if (!counter_config[cpu_cnt].enabled)
293+ continue;
294+
295+ event = counter_config[cpu_cnt].event & 255;
296+
297+ /*
298+ * Set event (if destined for PMNx counters)
299+ * We don't need to set the event if it's a cycle count
300+ */
301+ if (cnt != CCNT)
302+ armv7_pmnc_write_evtsel(cnt, event);
303+
304+ /*
305+ * Enable interrupt for this counter
306+ */
307+ armv7_pmnc_enable_intens(cnt);
308+
309+ /*
310+ * Reset counter
311+ */
312+ armv7_pmnc_reset_counter(cnt);
313+
314+ /*
315+ * Enable counter
316+ */
317+ armv7_pmnc_enable_counter(cnt);
318+ cnt_en[cnt] = 1;
319+ }
320+
321+ return 0;
322+}
323+
324+static inline void armv7_start_pmnc(void)
325+{
326+ armv7_pmnc_write(armv7_pmnc_read() | PMNC_E);
327+}
328+
329+static inline void armv7_stop_pmnc(void)
330+{
331+ armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
332+}
333+
334+/*
335+ * CPU counters' IRQ handler (one IRQ per CPU)
336+ */
337+static irqreturn_t armv7_pmnc_interrupt(int irq, void *arg)
338+{
339+ struct pt_regs *regs = get_irq_regs();
340+ unsigned int cnt;
341+ u32 flags;
342+
343+
344+ /*
345+ * Stop IRQ generation
346+ */
347+ armv7_stop_pmnc();
348+
349+ /*
350+ * Get and reset overflow status flags
351+ */
352+ flags = armv7_pmnc_getreset_flags();
353+
354+ /*
355+ * Cycle counter
356+ */
357+ if (flags & FLAG_C) {
358+ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), CCNT);
359+ armv7_pmnc_reset_counter(CCNT);
360+ oprofile_add_sample(regs, cpu_cnt);
361+ }
362+
363+ /*
364+ * PMNC counters 0:3
365+ */
366+ for (cnt = CNT0; cnt < CNTMAX; cnt++) {
367+ if (flags & (1 << (cnt - CNT0))) {
368+ u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt);
369+ armv7_pmnc_reset_counter(cnt);
370+ oprofile_add_sample(regs, cpu_cnt);
371+ }
372+ }
373+
374+ /*
375+ * Allow IRQ generation
376+ */
377+ armv7_start_pmnc();
378+
379+ return IRQ_HANDLED;
380+}
381+
382+int armv7_request_interrupts(int *irqs, int nr)
383+{
384+ unsigned int i;
385+ int ret = 0;
386+
387+ for (i = 0; i < nr; i++) {
388+ ret = request_irq(irqs[i], armv7_pmnc_interrupt,
389+ IRQF_DISABLED, "CP15 PMNC", NULL);
390+ if (ret != 0) {
391+ printk(KERN_ERR "oprofile: unable to request IRQ%u"
392+ " for ARMv7\n",
393+ irqs[i]);
394+ break;
395+ }
396+ }
397+
398+ if (i != nr)
399+ while (i-- != 0)
400+ free_irq(irqs[i], NULL);
401+
402+ return ret;
403+}
404+
405+void armv7_release_interrupts(int *irqs, int nr)
406+{
407+ unsigned int i;
408+
409+ for (i = 0; i < nr; i++)
410+ free_irq(irqs[i], NULL);
411+}
412+
413+#ifdef DEBUG
414+static void armv7_pmnc_dump_regs(void)
415+{
416+ u32 val;
417+ unsigned int cnt;
418+
419+ printk(KERN_INFO "PMNC registers dump:\n");
420+
421+ asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
422+ printk(KERN_INFO "PMNC =0x%08x\n", val);
423+
424+ asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val));
425+ printk(KERN_INFO "CNTENS=0x%08x\n", val);
426+
427+ asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val));
428+ printk(KERN_INFO "INTENS=0x%08x\n", val);
429+
430+ asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
431+ printk(KERN_INFO "FLAGS =0x%08x\n", val);
432+
433+ asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val));
434+ printk(KERN_INFO "SELECT=0x%08x\n", val);
435+
436+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
437+ printk(KERN_INFO "CCNT =0x%08x\n", val);
438+
439+ for (cnt = CNT0; cnt < CNTMAX; cnt++) {
440+ armv7_pmnc_select_counter(cnt);
441+ asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
442+ printk(KERN_INFO "CNT[%d] count =0x%08x\n", cnt-CNT0, val);
443+ asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val));
444+ printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n", cnt-CNT0, val);
445+ }
446+}
447+#endif
448+
449+
450+static int irqs[] = {
451+#ifdef CONFIG_ARCH_OMAP3
452+ INT_34XX_BENCH_MPU_EMUL,
453+#endif
454+};
455+
456+static void armv7_pmnc_stop(void)
457+{
458+#ifdef DEBUG
459+ armv7_pmnc_dump_regs();
460+#endif
461+ armv7_stop_pmnc();
462+ armv7_release_interrupts(irqs, ARRAY_SIZE(irqs));
463+}
464+
465+static int armv7_pmnc_start(void)
466+{
467+ int ret;
468+
469+#ifdef DEBUG
470+ armv7_pmnc_dump_regs();
471+#endif
472+ ret = armv7_request_interrupts(irqs, ARRAY_SIZE(irqs));
473+ if (ret >= 0)
474+ armv7_start_pmnc();
475+
476+ return ret;
477+}
478+
479+static int armv7_detect_pmnc(void)
480+{
481+ return 0;
482+}
483+
484+struct op_arm_model_spec op_armv7_spec = {
485+ .init = armv7_detect_pmnc,
486+ .num_counters = 5,
487+ .setup_ctrs = armv7_setup_pmnc,
488+ .start = armv7_pmnc_start,
489+ .stop = armv7_pmnc_stop,
490+ .name = "arm/armv7",
491+};
492diff --git a/arch/arm/oprofile/op_model_v7.h b/arch/arm/oprofile/op_model_v7.h
493new file mode 100644
494index 0000000..08f40ea
495--- /dev/null
496+++ b/arch/arm/oprofile/op_model_v7.h
497@@ -0,0 +1,101 @@
498+/**
499+ * @file op_model_v7.h
500+ * ARM v7 (Cortex A8) Event Monitor Driver
501+ *
502+ * @remark Copyright 2008 Jean Pihet <jpihet@mvista.com>
503+ * @remark Copyright 2004 ARM SMP Development Team
504+ * @remark Copyright 2000-2004 Deepak Saxena <dsaxena@mvista.com>
505+ * @remark Copyright 2000-2004 MontaVista Software Inc
506+ * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
507+ * @remark Copyright 2004 Intel Corporation
508+ * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
509+ * @remark Copyright 2004 Oprofile Authors
510+ *
511+ * @remark Read the file COPYING
512+ *
513+ * @author Zwane Mwaikambo
514+ */
515+#ifndef OP_MODEL_V7_H
516+#define OP_MODEL_V7_H
517+
518+/*
519+ * Per-CPU PMNC: config reg
520+ */
521+#define PMNC_E (1 << 0) /* Enable all counters */
522+#define PMNC_P (1 << 1) /* Reset all counters */
523+#define PMNC_C (1 << 2) /* Cycle counter reset */
524+#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */
525+#define PMNC_X (1 << 4) /* Export to ETM */
526+#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/
527+#define PMNC_MASK 0x3f /* Mask for writable bits */
528+
529+/*
530+ * Available counters
531+ */
532+#define CCNT 0
533+#define CNT0 1
534+#define CNT1 2
535+#define CNT2 3
536+#define CNT3 4
537+#define CNTMAX 5
538+
539+#define CPU_COUNTER(cpu, counter) ((cpu) * CNTMAX + (counter))
540+
541+/*
542+ * CNTENS: counters enable reg
543+ */
544+#define CNTENS_P0 (1 << 0)
545+#define CNTENS_P1 (1 << 1)
546+#define CNTENS_P2 (1 << 2)
547+#define CNTENS_P3 (1 << 3)
548+#define CNTENS_C (1 << 31)
549+#define CNTENS_MASK 0x8000000f /* Mask for writable bits */
550+
551+/*
552+ * CNTENC: counters disable reg
553+ */
554+#define CNTENC_P0 (1 << 0)
555+#define CNTENC_P1 (1 << 1)
556+#define CNTENC_P2 (1 << 2)
557+#define CNTENC_P3 (1 << 3)
558+#define CNTENC_C (1 << 31)
559+#define CNTENC_MASK 0x8000000f /* Mask for writable bits */
560+
561+/*
562+ * INTENS: counters overflow interrupt enable reg
563+ */
564+#define INTENS_P0 (1 << 0)
565+#define INTENS_P1 (1 << 1)
566+#define INTENS_P2 (1 << 2)
567+#define INTENS_P3 (1 << 3)
568+#define INTENS_C (1 << 31)
569+#define INTENS_MASK 0x8000000f /* Mask for writable bits */
570+
571+/*
572+ * EVTSEL: Event selection reg
573+ */
574+#define EVTSEL_MASK 0x7f /* Mask for writable bits */
575+
576+/*
577+ * SELECT: Counter selection reg
578+ */
579+#define SELECT_MASK 0x1f /* Mask for writable bits */
580+
581+/*
582+ * FLAG: counters overflow flag status reg
583+ */
584+#define FLAG_P0 (1 << 0)
585+#define FLAG_P1 (1 << 1)
586+#define FLAG_P2 (1 << 2)
587+#define FLAG_P3 (1 << 3)
588+#define FLAG_C (1 << 31)
589+#define FLAG_MASK 0x8000000f /* Mask for writable bits */
590+
591+
592+int armv7_setup_pmu(void);
593+int armv7_start_pmu(void);
594+int armv7_stop_pmu(void);
595+int armv7_request_interrupts(int *, int);
596+void armv7_release_interrupts(int *, int);
597+
598+#endif
599diff --git a/include/asm-arm/arch-omap/irqs.h
600b/include/asm-arm/arch-omap/irqs.h
601index c80e160..89ca90e 100644
602--- a/include/asm-arm/arch-omap/irqs.h
603+++ b/include/asm-arm/arch-omap/irqs.h
604@@ -297,6 +297,7 @@
605 #define INT_243X_HS_USB_DMA 93
606 #define INT_243X_CARKIT_IRQ 94
607
608+#define INT_34XX_BENCH_MPU_EMUL 3
609 #define INT_34XX_ST_MCBSP2_IRQ 4
610 #define INT_34XX_ST_MCBSP3_IRQ 5
611 #define INT_34XX_SYS_NIRQ 7